Python Package Management for the Paranoid
This tweet by Kenneth Reitz (author of many Python packages), caught my eye the other week
Kenneth is highlighting a significant security risk to those packages, that some malicious person could compromise his account, publish requests and anyone that installs the package would be running arbitrary code. Yikes.
I’m a little security conscious (paranoid) when it comes to these things, sign my git commits and packages using a key that is published to the repo. It’s worth noting that this takes a while to setup and I know that most people haven’t (because the “verified” label in GitHub is a lesser-spotted animal).
Creating an online key
PGP and GPG are confusingly similar. PGP was originally proprietary, but the OpenPGP standard came and was later widely adopted. You can choose to use either, for my case I use GPG.
$ gpg --gen-key
Choose RSA, 4096 bit encryption and enter your primary email address (this also needs to be one of your verified emails registered with GitHub).
Upload that key to https://pgp.mit.edu by getting it’s ID gpg --list-secret-keys --keyid-format LONG
and then exporting the text from gpg --armor --export <your key id>
. Simply copy+paste the text into their website and your public key will be public domain. Your key should have others verify it, as well as your identity via a signing exchange, but that’s too much detail for this article.
Configuring GitHub
1. Stop using HTTPS remotes
Moving completely to 2FA auth with GitHub needs a call to git remote get-url origin
(assuming your remote is called origin) for repos that you need permissions to pull or push to. This will tell you whether you’re using HTTPS or git (SSH) to connect. You can replace an existing URL with a SSH address easily by calling git remote set-url origin git@github.com:myuser/myrepo.git
2. Enable 2FA
In your GitHub profile, enable two-factor. This stops you from ever having your compromised password used to change projects, upload dodgy code, etc. It takes 2 minutes.
3. Upload your GPG key to GitHub
In the SSH and GPG keys section, share the public key with GitHub (the asc file) so that your commits are verified (I’ll explain how to do this later).
Signing in Git
Earlier we created a GPG key (or maybe you already had one). Now we need to tell Git to use it. Find the long identifier of the key with this command gpg --list-secret-keys --keyid-format LONG
and paste that into your git configuration as so,
git config --global user.signingkey <Long key id>
Unless you tell Git, it won’t sign your commits. There are flags for signing commits, merges and tags. git tag --sign
, git commit -D
and git merge -D
People tend to forget, so it makes sense to set a shell alias for git commit
to be git commit -D
, likewise with git merge.
Try committing and pushing some code up to GitHub. If all has been done correctly you should see a nice green tick
PyPi and PGP
In PyPi, you can upload the short ID for your GPG key into the profile,
Signing packages is pretty straightforward, when you publish the source and wheel, include the identity and the request to sign before upload.
python setup.py sdist bdist_wheel upload --sign --identity <your PGP key id>
Full details on how to sign using the Python API or check signed releases can be found here http://pythonhosted.org/distlib/tutorial.html#signing-a-distribution
Published, signed source packages should have MD5 and PGP (asc files) in PyPi. This is shown in the pgp link in brackets.