How to verify the Authenticity of a Python download with gpg?

I’m having trouble finding instructions on the Internet, regarding how to verify the authenticity of my Python download with gpg. Can you help me?

# Python 3.4.10 info:

# Gzipped source tarball:

# MD5 Sum (Gzipped source tarball):

# GPG signature:

# ______________________________________________________________________________
# Check "Python-3.4.10.tgz" file integrity.

$ md5sum -b Python-3.4.10.tgz              
"2452f4d809ae9d88011ccafe12c4b6d3 *Python-3.4.10.tgz"

# ______________________________________________________________________________
# Verify the authenticity of "Python-3.4.10.tgz".

$ gpg --verify Python-3.4.10.tgz.asc Python-3.4.10.tgz                    

# gpg: Signature made Mon 18 Mar 2019 01:16:20 PM EDT
# gpg:                using RSA key 97...0D
# gpg: Can't check signature: No public key

# ______________________________________________________________________________

How do I interpret the pgp response? What is good and what is bad response, when performing the gpg verification on a Python download file?

There’s some instructions on what to do on the main Downloads page - scroll down to “OpenPGP Public Keys”.

You need to download (from a trusted source!) the public key that was used to sign the release before you can verify the signature. For the 3.4.10 release, it looks like the signature was made using Larry Hastings’ key, 3A5C A953 F73C 700D.

You can download and import a public key from a keyserver using the command gpg --recv-keys <KEY>. In this case, you’d want to run

$ gpg --recv-keys 3A5CA953F73C700D

Depending on your gpg configuration, you may get a message like

gpg: key 3A5CA953F73C700D: new key but contains no user ID - skipped

(see this SuperUser question on why). If you do, try using a different keyserver, like Ubuntu’s keyserver:

$ gpg --keyserver hkps:// --recv-keys 3A5CA953F73C700D
gpg: key 3A5CA953F73C700D: public key "Larry Hastings <>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Once you’ve imported the public key, you’ll be able to verify the signature using the command you ran before. You should see an output like the following:

$ gpg2 --verify Python-3.4.10.tgz.asc                                     
gpg: assuming signed data in 'Python-3.4.10.tgz'
gpg: Signature made Mon 18 Mar 2019 01:16:20 PM EDT
gpg:                using RSA key 97FC712E4C024BBEA48A61ED3A5CA953F73C700D
gpg: Good signature from "Larry Hastings <>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 97FC 712E 4C02 4BBE A48A  61ED 3A5C A953 F73C 700

The line you want to look for is Good signature from "Larry Hastings <>". That means that the tarball you downloaded was indeed signed using the key 3A5C A953 F73C 700D.

For the purposes of verifying the signature, you can ignore the scary line WARNING: This key is not certified with a trusted signature! if present.
See GPG why is my trusted key not certified with a trusted signature? and for more on why this appears and what “trust” means in GPG.


If your threat model is such that you need to verify the GPG signature, you haven’t gained much, if anything, if the verification is made against an untrusted public key.

If you need to verify a GPG signature, you are concerned that a malicious party may have altered the data you are trying to access. The signature verification is only worth something if it comes via a different channel than the potentially compromised one. If you just download the public key without verifying its ownership, the hypothetical malicious party may just as easily have swapped it for their own key.

The trust model used by GPG is called Web of Trust. Basically, it relies on people physically meeting up, verifying each others’ identities with documentation such as driver’s licenses or passports, and then signing each others’ public keys. Signing a public key means that you trust that the key owner is who they say they are.

In order to trust a public key A, you must either have met the owner of key A personally and signed their key, or met and signed the key (key B) of someone who met the owner of key A and signed it. By trusting key B, you can indirectly trust key A. This can of course be extended in further steps, which is what creates the Web of Trust (WoT).

If you are not personally in Larry Hasting’s WoT, you gain nothing by verifying his signature. If you are concerned that a malicious party may be actively interfering with your access to Python’s source code, you need to become part of that WoT in order to have any level of trust in what you download.

If you are only concerned with verifying the integrity of the downloaded data against accidental changes, the MD5 sum is sufficient.