2009-08-31 21:56Simply signing GPG keysCryptography is hard to do right, and even if it is implemented correctly, the user is often required to perform some complicated operations to make use of it. One area of cryptography which involves a great deal of activity from the user is the signing of public keys used in public key cryptography. Not only does it usually require users actually meet each other and do some sort of identity verification, it then requires quite an involved process at the computer involving retrieving keys, checking signatures, and sending emails. To automate this as much as possible, I have come up with a little script which helps me perform some GPG and email operations quickly and simply, without, I hope, reducing my security. AlternativesSeveral people have asked me “Why don’t you just use caff?” and it’s a valid question so I might as well include an answer here. Firstly I like to understand the operations I am performing in some detail, and I feel I have learnt a lot by carrying out the process by hand, and then turning those commands into a script. It is also easier to modify your own script than someone else’s, so I’d like to think my script gives me some more flexibility. Also, caff is written in Perl, which I’m not fluent at, so the effort required to edit the script (should I ever have a need to) is more than just the effort of reading some unfamiliar source code. Finally there is my paranoia about running a script which asks for your most secret of secret passwords, and then sends out encrypted emails to people. Of course, if you can’t trust caff then you can’t trust your terminal, or GPG, or your kernel, but I think there are different attack vectors there, and it is harder to remove those potential attack surfaces. I did once ask someone how one could be sure that caff was trustworthy, and they said “You open the script in a text editor, and as it’s Perl, if it looks like line noise then it’s probably safe, or at least that’s as sure as anyone can be with code like that”. The script#!/bin/bash keyid=$1 email=$2 gpg —keyserver-options import-minimal —recv-keys $1 gpg —fingerprint $1 echo "Is this fingerprint correct? (y/N)" read happy if [[ $happy != "y" ]] then echo "No keys for you!" exit fi # To sign just the primary uid, use: #gpg —edit-key $1 uid 1 sign # To choose which uid(s) to sign, use: #gpg —sign-key $1 # To guess the uid from the email address, use: uid=`gpg —list-keys $email | grep "^uid" | grep -n $email | sed ’s/:.*//’` # Then to sign just the uid for that email address, use: gpg —edit-key $1 uid $uid sign cp before-key.txt $1.txt # Create a version of their key which includes my signature. Save it as $1.txt . gpg —export —armor $1 >> $1.txt # Create an encrypted version of $1.txt . GPG will save it as $1.txt.asc . gpg —encrypt —armor —recipient $1 $1.txt cp before-encrypted.txt $1.txt cat $1.txt.asc >> $1.txt # To use the email address given in the primary uid use: # email=`gpg —list-keys $1 | grep -m 1 uid | sed ‘s/.*<//’ | sed ‘s/>.*//’` mailx -s "Your signed PGP key" $email < $1.txt # Don’t trust a signature which hasn’t been unencrypted by the recipient of the email. gpg —delete-key $1 # Later, when they have uploaded the key themselves, run this: #gpg —recv-keys $1 ExplanationBefore running this script, it is assumed you have picked up key slips at a key signing party, which contain at least a key fingerprint, a UID for that key and an email address associated with that UID. The script takes two arguments: the UID of the key and its email address, then it uses the UID to download the relevant key from a keyserver. As a UID is only 4 bytes (the last 4 bytes of the fingerprint), it is possible that someone could generate a key with the same UID as someone else, and you wouldn’t want to sign that key by mistake, so the next step is for the script to output the full 20 byte fingerprint, which you are expected to check by eye against the key slip you received. Assuming the fingerprint matches, it is assumed this is the right key, and the script tries to guess which of the UIDs within the key has the email address you are interested in. The UIDs are each given an index number by GPG which you must specify when performing operations involving one of them, and GPG does not let you request this UID number for a given email address, so a rather fragile one-liner has to be used to extract it. The commented code above this one-liner can be used instead if you want the script to prompt you at this point rather than guessing, or to just pick the primary UID. Once the UID has been chosen some how, the command to sign that UID is executed, which will prompt you to type your secret passphrase in. Your keyring now contains a key with an extra signature, and this key needs to be emailed to its owner, so the first thing to do is build the body of that email. I have written a nice file called before-key.txt which explains “Below is your key:” or similar, so the script makes a copy of it for editing and gives it a new name based on the UID. An exported, armoured version of the key is appended to the end of this text file, which creates a message which could be used to extract the new signature from. However, it hasn’t yet been determined that the person with the private half of this key really does have access to the email address given in the UID. The way to do that is to encrypt the text file that has just been created so that the signature can only be accessed by someone with the key. This encrypted file is automatically given a new name by the encryption process, leaving the old file around, which can be replaced by before-encrypted.txt, another little message saying something like “Below is an encrypted message containing your key:”. The contents of the encrypted file are then appended to this file, and this file is then sent to the specified email address. To leave your keyring in the state it was before running the script, though, the signed key must be removed from it, but it can later be downloaded when the recipient has presumably decrypted your message and uploaded your signature. ConclusionOne severe limitation with this script as it stands is that it only signs one UID and sends a single email. If you want to sign multiple UIDs you have to run the script several times with different arguments, and type your passphrase in each time. In future I will probably update this script so that it loops over each UID and sends an email for each one, as this is what participants in a key signing party expect and it is only polite to oblige. Another slight annoyance is that after you run the command to sign the key and it’s asked you all the questions about how carefully you’ve checked it and whether you are sure, and you’ve typed in your passphrase, it then returns you to a GPG command line where you have to enter q to tell it to quit then enter y to tell it you’re sure you want to save the changes you’ve made. Finally, you may need or want to configure things in your gpg.conf file so that the script works properly. I would recommend keyserver followed by the address of the default keyserver you want to use, and ask-cert-level to make it ask you how much you have verified the key you are signing. That’s a lot of hassle, so why don’t we just send the email unencrypted, and why does checking someone’s driver’s license make their key more trustworthy? |
QuicksearchCategoriesSyndicate This BlogBlog Administration |
Signing people’s keys is one problem, but when people sign your key that requires its own procedure with its own set of potential issues.
Tracked: Nov 30, 21:30