In the last post, I built a contact us form using PGP encryption. I wanted to follow up with another cool encryption feature, signing. I will be walking through how you can sign your git commits. As well as any files/packages you build.
Signing is a form of encryption authentication. When encrypting a message in PGP, you are able to sign it with your private key. The recipient could then verify that signature with your public key. This would allow them to verify the message was in fact sent by you.
This concept of signing applies to more than messaging. Even more than encryption itself. I wanted to give some examples of how you could start signing your work as a developer. This signing doesn't involve any encryption. It serves to allow others to verify items that you have signed as yours.
This post assumes you have gpg installed.
To begin signing, you will need public and private keys. The private key would be for you to sign with. The public key can be used to verify that signature.
The first step will be generating your PGP key. Run the following command to generate.
It will ask you to provide your name, email, and a password. It will spit out information about your newly generated key.
pub rsa2048 2019-12-04 [SC] [expires: 2021-12-03] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX uid David Boland <[email protected]> sub rsa2048 2019-12-04 [E] [expires: 2021-12-03]
You will need reference to your key going forward. To get the Id, run the command:
gpg --list-secret-keys --keyid-format LONG
It will spit out your keys as before, but in the specified key format:
sec rsa2048/DFD20A3D39A1913 2019-12-04 [SC] [expires: 2021-12-03] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX uid [ultimate] David Boland <[email protected]> ssb rsa2048/XXXXXXXXXXXXXXXX 2019-12-04 [E] [expires: 2021-12-03]
The data after "rsa2048/" in the sec section is the user Id for that key. So in our case
DFD20A3D39A1913. I will use it as an example going forward. But you would use your key Id.
To verify signatures, people will need access to your public key. To export it from gpg, run the following command:
gpg --armor --export DFD20A3D39A1913
Your key will start with
-----BEGIN PGP PUBLIC KEY BLOCK----- and end with
-----END PGP PUBLIC KEY BLOCK-----.
To sign your commits, you need to configure git locally on your machine. You also need to provide Github with your public key so that they can verify the signature on the commits.
In order to sign your commits, there are a couple configuration updates that need to be made in git. First, is specifying your key that was created previously.
git config --global user.signingkey DFD20A3D39A1913
the 'global' flag makes this setting global for the specified user.
Next you may need to specify to git the instance of gpg that you are using. After setting up I got the following error.
gpg: skipped "name <[email protected]>": secret key not available gpg: signing failed: secret key not available error: gpg failed to sign the data fatal: failed to write commit object
You will get this error if you do not specify the
user.signingkey. You will also get this if you have multiple gpg instances and git looks to the wrong one.
In my case I am using a console emulator, which ships with its own instance of gpg. So I needed to specify the path to my gpg instance.
git config --global gpg.program gpg
At this point you can sign your commits. When committing, you just need to add the
You are able set up automatic signing without having to specify the flag. You can globally set the
git config --global commit.gpgsign true
In Github, navigate to your settings and there is an option for SSH and GPG keys. Your keys will be listed here.
In the GPG section, select New GPG key. In the text field provided, paste the public key you exported previously.
Once you push your commit, you will see it listed as "Verified" by Github.
PGP also provides a method for signing files. This is useful for signing release packages and executables. This allows users to verify the author and integrity of the package. Users may want this level of verification for security reasons. Especially if the package handles sensitive information.
There are three methods for signing with GPG. Signing, clear signing, and detached signing.
Standard signing and clear signing both effect the file itself. Standard signing is used with encryption. Clear signing wraps the input with plaintext signature. Since we don't want this type of modification, we will work with detached signature.
Detached signing creates a signature in a separate file. We can then provide the package, and provide the signature file from a trusted source. The user can then verify the package against it.
To create a signed file:
gpg --detach-sign --sign-with DFD20A3D39A1913 -o package.sig package.exe
--detach-sign flag indicates that we want a detached signature.
--sign-with flag allows you to provide the id of the key you want to sign with.
The final flag,
-o allows you to specify the output file. Traditionally you use either a .sig or a .gpg extension.
And finally you specify the file you want to sign. In order to perform verification, you run the following command:
gpg --verify package.sig package.exe
The think the idea of signing is pretty awesome. As developers, we sometimes forget how much reach our work can have. As code/programs are shared online, it can be beneficial to verify its source.
This concept of signing isn't fool proof. Users can opt not to validate. Signers can loose their private keys. And the signature doesn't imply the code itself can be trusted. Signatures can only verify its source. But when done correctly, code signing can be useful.
As always, if you have any questions. Either about signing, or encryption in general, feel free to reach out.