head 1.1; branch 1.1.1; access ; symbols MAXIMUM_RPM_1_0:1.1.1.1 VENDOR:1.1.1; locks ; strict; comment @# @; 1.1 date 2001.08.28.12.07.09; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.08.28.12.07.09; author rse; state Exp; branches ; next ; desc @@ 1.1 log @Initial revision @ text @
In this chapter, we'll explore the steps required to add a digital signature to a package, using the software known as Pretty Good Privacy, or PGP. If you've used PGP before, you probably know everything you'll need to start signing packages in short order.
On the other hand, if you feel you need a bit more information on PGP before starting, please refer to Appendix [*] on page [*] for a brief introduction. Once you feel comfortable with PGP, come on back and learn how easy signing packages is...
The reason for signing a package is to provide authentication. With a signed package, it's possible for your user community to verify that the package they have was in your possession at some time and has not been changed since then. That ``not changed'' part is also a good reason to sign your packages, as digital signatures are a very robust way to guard against any modifications to the package.
Of course, as with anything else in life, adding a digital signature to a package isn't an ironclad guarantee that everything is right with the package, but it's about as sure a thing as humans can make it.
OK, we've convinced you that signing packages is a good idea. Now we've got to make sure PGP and RPM are up to the task. As you might imagine, there are two parts to this process: one for PGP, and one for RPM. Let's get PGP ready first.
There is really very little to be done to PGP, assuming it's been installed properly. The only thing required is to generate a key pair. As mentioned in our mini-primer on PGP, the key pair consists of a secret key and a public key. In terms of signing packages, you will use your secret key to do the actual signing. Anyone interested in checking your signature will need your public key.
Creating a key pair is quite simple. All that's required is to issue a pgp -kg command, enter some information, and create some random bits. Here's an example key generating session:
# pgp -kg
Pretty Good Privacy(tm) 2.6.3a - Public-key encryption for the masses. (c) 1990-96 Philip Zimmermann, Phil's Pretty Good Software. 1996-03-04 Uses the RSAREF(tm) Toolkit, which is copyright RSA Data Security, Inc. Distributed by the Massachusetts Institute of Technology. Export of this software may be restricted by the U.S. government. Current time: 1996/10/31 00:42 GMT Pick your RSA key size: 1) 512 bits- Low commercial grade, fast but less secure 2) 768 bits- High commercial grade, medium speed, good security 3) 1024 bits- "Military" grade, slow, highest security
Generating an RSA key with a 1024-bit modulus. You need a user ID for your public key. The desired form for this user ID is your name, followed by your E-mail address enclosed in <angle brackets>, if you have an E-mail address. For example: John Q. Smith <12345.6789@@compuserve.com> Enter a user ID for your public key:Example Key for RPM Book
You need a pass phrase to protect your RSA secret key. Your pass phrase can be any sentence or phrase and may have many words, spaces, punctuation, or any other printable characters.Enter pass phrase: <passphrase> (Not echoed)
Note that key generation is a lengthy process. We need to generate 952 random bits. This is done by measuring the time intervals between your keystrokes. Please enter some random text on your keyboard until you hear the beep:(Many random characters were entered)
0 * -Enough, thank you. ............................................ ................................**** ...**** Pass phrase is good. Just a moment.... Key signature certificate added. Key generation completed. #
Let's review each of the times PGP required information. The first thing PGP needed to know was the key size we wanted. Depending on your level of paranoia, simply choose an appropriate key size. In our example, we chose the ``They're out to get me'' key size of 1024 bits.
Next, we needed to choose a user ID for the key. The user ID should be descriptive and should also include sufficient information for someone to contact you. We entered Example Key for RPM Book, which goes against our suggestion, but is sufficient for the purposes of our example.
After entering a user ID, we needed to add a pass phrase. The pass phrase is used to protect your secret key, so it should be something difficult for someone else to guess. It should also be memorable for you, because if you forget your pass phrase, you won't be able to use your secret key! I entered a couple of words and numbers, put together in such a way that no one could ever guess I typed rpm2kool4words
Oops...
The pass phrase is entered twice, to ensure that no typing mistakes were made. PGP also performs some cursory checks on the pass phrase, ensuring that the phrase is at least somewhat secure.
Finally comes the strangest part of the key-generation process, creating random bits. This is done by measuring the time between keystrokes. The secret here is to not hold down a key so that it auto-repeats and to not wait several seconds between keystrokes. Simply start typing anything (even nonsense text) until PGP tells you you've typed enough.
After generating enough random bits, PGP takes a minute or so to create the key pair. Assuming everything completed successfully, you'll see an ending message similar to the one above. You'll also find, in a subdirectory of your login directory called .pgp, the following files:
# ls -al /.pgp
total 6 drwxr-xr-x 2 root root 1024 Oct 30 19:44 . drwxr-xr-x 5 root root 1024 Oct 30 19:44 .. -rw------- 1 root root 176 Oct 30 19:44 pubring.bak -rw------- 1 root root 331 Oct 30 19:44 pubring.pgp -rw------- 1 root root 408 Oct 30 19:44 randseed.bin -rw------- 1 root root 509 Oct 30 19:44 secring.pgp #
For those interested in learning exactly what each file is, feel free to consult any of the fine books on PGP. For the purposes of signing packages, all we need to know is where these files are located.
That's it! Now it's time to configure RPM to use your newly generated key.
RPM's configuration process is quite straightforward. It consists of adding a few rpmrc entries in a file of your choice. For more information on rpmrc files in general, please see Appendix [*] on page [*].
The entries that need to be added to an rpmrc file are:
Let's check out the entries.
The signature entry is used to select the type of signature that RPM is to use. At the time this book was written, the only legal value is pgp. So you would enter:
signature: pgp
The pgp_name entry gives RPM the user ID of the key it is to sign packages with. In our key generation example, the user ID of the key we created was Example Key for RPM Book, so this is what our entry should look like:
pgp_name: Example Key for RPM Book
The pgp_path entry is used to define the path to the directory where the keys are kept. This entry is not needed if the environment variable PGPPATH has been defined. In our example, we didn't move them from PGP's default location, which is in the subdirectory .pgp, off the user's login directory. Since we generated the key as root, our path is /root/.pgp. Therefore, our entry would look like this:
pgp_path: /root/.pgp
And that's it. Now it's time to sign some packages.
There are three different ways to sign a package:
Lets take a look at each one, starting with build-time signing.
The - -sign option is used to sign a package as it is being built. When this option is added to an RPM build command, RPM will ask for your PGP pass phrase. If the pass phrase is correct, the build will proceed. If not, the build stops immediately.
Here's an example of - -sign in action:
# rpm -ba - -sign blather-7.9.spec
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good. * Package: blather ... Binary Packaging: blather-7.9-1 Finding dependencies... ... Generating signature: 1002 Wrote: /usr/src/redhat/RPMS/i386/blather-7.9-1.i386.rpm ... Source Packaging: blather-7.9-1 ... Generating signature: 1002 Wrote: /usr/src/redhat/SRPMS/blather-7.9-1.src.rpm #
Once the pass phrase is entered, there's very little that is different from a normal build. The only obvious difference is the Generating signature message in both the binary and source packaging sections. The number following the message indicates that the signature added was created using PGP.1
Notice, that since RPM only signs the source and binary package files, only the -bb, and -ba options make any sense when used with - -sign. This is due to the fact that only the -bb and -ba options create package files.
If we issue a quick signature check using RPM's - -checksig option, we can see that there is, in fact, a PGP signature present:
# rpm - -checksig blather-7.9-1.i386.rpm
blather-7.9-1.i386.rpm: size pgp md5 OK
#
It's clear to see that, in addition to the usual size and MD5 signatures, the package has a PGP signature.
You might be wondering how the - -sign option would work if more than one package is to be built. Do you have to enter the pass phrase for every single package you build? The answer is no, as long as you build the packages with a single RPM command. Here's an example:
# rpm -ba - -sign b*.spec
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good. * Package: blather ... Binary Packaging: blather-7.9-1 ... Generating signature: 1002 Wrote: /usr/src/redhat/RPMS/i386/blather-7.9-1.i386.rpm ... Source Packaging: blather-7.9-1 ... Generating signature: 1002 Wrote: /usr/src/redhat/SRPMS/blather-7.9-1.src.rpm ... * Package: bother ... Binary Packaging: bother-3.5-1 ... Generating signature: 1002 Wrote: /usr/src/redhat/RPMS/i386/bother-3.5-1.i386.rpm ... Source Packaging: bother-3.5-1 ... Generating signature: 1002 Wrote: /usr/src/redhat/SRPMS/bother-3.5-1.src.rpm #
Using the - -sign option makes it as easy to sign one package as it is to sign one hundred. But what happens if you need to change your public key? Will you need to rebuild every single one of your packages just to update the signature?
As we mentioned at the end of the previous section, from time to time it may be necessary to change your public key. Certainly this would be necessary if your key's security was compromised, but other, more mundane situations might require this.
Fortunately, RPM has an option that permits you to replace the signature on an already-built package, with a new one. The option is called - -resign, and here's an example of its use:
# rpm - -resign blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
#
While the output is not as exciting as a package build, the - -resign option can be a life-saver if you need to change a package's signature, and you don't want to rebuild.
As you might have guessed, the - -resign option works properly on multiple package files:
# rpm - -resign b*.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
bother-3.5-1.i386.rpm:
#
Unfortunately, older package files cannot be re-signed. The package file must be in version 3 format, at least. If you attempt to resign a package that is too old, here's what you'll see:
# rpm - -resign blah.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blah.rpm:
blah.rpm: Can't re-sign v2.0 RPM
#
Not sure what version your package files are at? Just use the file command to check:
# file blather-7.9-1.i386.rpm
blather-7.9-1.i386.rpm: RPM v3 bin i386 blather-7.9-1
#
The ``v3'' in file's output indicates the package file format.
The - -addsign option, as the name suggests, is used to add another signature to the package. It's pretty easy to see why someone would want to have a package that had been signed by the package builders. But what reason would there be for adding a signature to a package?
One reason to have more than one signature on a package would be to provide a means of documenting the path of ownership from the package builder to the end-user.
As an example, the division of a company creates a package and signs it with the division's key. The company's headquarters then checks the package's signature and adds the corporate signature to the package, in essence stating that the signed package received by them is authentic.
Continuing the example, the doubly-signed package makes its way to a retailer. The retailer checks the package's signatures and, when they check out, adds their signature to the package.
The package now makes its way to a company that wishes to deploy the package. After checking every signature on the package, they know that it is an authentic copy, unchanged since it was first created. Depending on the deploying company's internal controls, they may choose to add their own signature, thereby reassuring their employees that the package has received their corporate ``blessing''.
After this lengthy example, the actual output from the - -addsign option is a bit anti-climactic:
# rpm - -addsign blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
#
If we check the signatures of this package, we'll be able to see the multiple signatures:
# rpm - -checksig blather-7.9-1.i386.rpm
blather-7.9-1.i386.rpm: size pgp pgp md5 OK
#
The two pgp's in - -checksig's output clearly shows that the package has been signed twice.
As with the - -resign option, the - -addsign option cannot do its magic on pre-V3 package files:
# rpm - -addsign blah.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blah.rpm:
blah.rpm: Can't re-sign v2.0 RPM
#
OK, the error message may not be 100% accurate, but you get the idea.
Another thing to be aware of is that the - -addsign option does not check for multiple identical signatures. Although it doesn't make much sense to do so, RPM will happily let you add the same signature as many times as you'd like:
# rpm - -addsig blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
# rpm - -addsig blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
# rpm - -addsig blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
# rpm - -addsig blather-7.9-1.i386.rpm
Enter pass phrase: <passphrase> (Not echoed)
Pass phrase is good.
blather-7.9-1.i386.rpm:
# rpm - -checksig blather-7.9-1.i386.rpm
blather-7.9-1.i386.rpm: size pgp pgp pgp pgp md5 OK
#
As we can see from - -checksig's output, the package now has four identical signatures. Maybe this is the digital equivalent of pressing down extra hard while writing your name...