I want to sign some Python code files I wrote, because they are plug-in modules for one of my projects. For distributing it, I want that the user can be sure a plug-in is verified and safe (because written by me or somebody I trust) and was not modified.
The software is just a open-source hobby project, therefore I don't want to spend any money for buying an official certificate. Instead, I assume that the main program is always valid and can be trusted without additional verification. If somebody downloads it from any other location than my GitHub repository, it's their fault.
From what I've read, signing is usually done by creating an asymmetric key pair, calculating a strong cryptographic hash value (e.g. SHA-512) from the code file, encrypting the hash using my private key and storing that signature in a separate file to be shipped with the original code file.
The main program will then have to decrypt the signature using the public key that is saved in plain-text in the main program's source code, calculate the same hash function of the code file and then compare it to the decrypted one. If they match, the plug-in can be trusted.
So now my question:
How do I easily create a strong asymmetric key pair with Ubuntu tools and how do I easily calculate a cryptographic hash value of a file?
Automatizing the signing process in a script (using always the same key) would be great.
Much of this answer is ripped off from the Arch Wiki and the GnuPG documentation. Any recommendations in this answer are purely my opinion, and should be taken with a tonne of salt.
Creating a PGP key
GUI
Open the Passwords and Keys app (aka
seahorse
), and click+
(or go to File->New, or press CtrlN) to see:Select PGP key, and enter your details. I'm impersonating Byte Commander:
RSA and 2048 bits are fine for most purposes. If you only want to use it for signing, pick the RSA (sign only) option from the drop-down menu, but you shouldn't need to - this can be handled using subkeys. You can leave a comment. Keeping an expiry date on your key is also useful. Click Create.
Enter a suitably long password (and I mean long, my example is short, IMO), and click Ok:
Seahorse doesn't seem to have any feedback, unlike the CLI. Wait around for a while, doing whatever you want to do, while it gathers entropy and creates a key. It might take a while. After which, you'll see they key in the PGP Keys section:
CLI
To generate a key from the command line, just run
gpg --gen-key
. It will ask you for the same details that the GUI did:Note how GnuPG tells us it needs more entropy. Wish seahorse did too. But then again, it feels like GnuPG is acting like Oliver Twist. :P
Publishing your key
Now, we need to get our public key out there, so people can verify things using it.
GUI
Head back to the list of PGP keys in the
seahorse
app (see last screenshot). Select the key(s) you want to export, and in the Remote menu, pick Sync and Publish Keys:The Sync button will be disabled if you haven't selected a server to publish to. Do so, by clicking on the Key Servers button:
I picked Ubuntu's server.
Now, you can click the Sync button and have it published to Ubuntu's keyserver (sorry for the spam, Ubuntu!).
CLI
With the CLI, you need the key ID of the key you want to publish. It's the very last line of the output when creating the key (
8AE670A6
). If you don't remember what it is, just rungpg --list-keys
. To publish:Sorry, MIT.
Signing
I don't know of a convenient GUI method of signing a document, yet.
Once you have created the file you want to sign, head to the terminal. Try
gpg --list-keys
:You can sign the file using two methods:
Signing with encryption
If you're on a desktop session, chances are you'll be greeted with a graphical password prompt. For example, in GNOME:
If the recipient has your public key, they can verify it, or get the decrypted content:
Signing with cleartext
You might not want to encrypt the contents, for example, when sending a mail. In which case, use the
--clearsign
option:Signing, with a separate file for signature (detached signature)
Lastly, for some files, you can't have the signature in the document. For example, packaging files, or the metadata for a repository, both have content of a specific nature that don't easily allow embedded signatures. In this case, you use the
--detached-sig
option:Note
In encryption+signing and in detached signatures, the output of
gpg
is binary. You can have GnuPG output base64-encoded data using the--armor
option (ASCII-armoured).Automation
To script signing, you could:
stdin
. See this Unix & Linux post for some options.Create a asymmetric key with gpg
Use gpg to sign your file (your private key is used)
Test the signature file (your public key is used)
Example output