Tired of ads? Upgrade to paid account and never see ads again!

Previous Entry Share Next Entry
Feeding entropy to GnuPG on Fedora

In a previous post, I mentioned we are putting together an RPM build server at work. The RPMs that are built are signed by an encryption key and uploaded to the Yum server. The GnuPG (GPG) signing will give us confidence that the RPMs were from the build server and weren't tampered with since they were built and copied to the Yum repository.

At this point, the security of the signing key is not important. I say this confidently even after the recent package signing compromise at Fedora and Red Hat. We want to have automated package signing and we're only building packages for distribution inside the office.

One nice feature of GnuPG is its automatic key generation. The RPM build server is generating its own key, and preferably as non-interactive as possible. Unfortunately, this requires entropy to work consistently.

For information about automatically generating keys with GPG see the section "Unattended key generation" in the DETAILS file that comes with GnuPG. That documentation can be found on a GNU/Linux system with the following command.

  $ less -p "^Unattended" /usr/share/doc/gnupg-*/DETAILS

As the summary says:

This feature allows unattended generation of keys controlled by a parameter file. To use this feature, you use --gen-key together with --batch and feed the parameters either from stdin or from a file given on the command line [sic].

Here's an example of automatically generating a secret GPG key.

  $ cat gpg-key.conf
  %echo Generating a package signing key
  Key-Type: DSA
  Key-Length: 1024
  Subkey-Type: ELG-E
  Subkey-Length: 2048
  Name-Real: Build Server
  Name-Email: builds@site.org
  Expire-Date: 0
  Passphrase: Does not ex1st!
  %echo Done
  $ gpg --batch --gen-key gpg-key.conf \
        > gpg-keygen.log \
        2> gpg-keygen_error.log

Those familliar with generating keys know that it is an extremely interactive process. Not just for entering the details about the key, but because you need to inject entropy into the computer to ensure the newly generated key is random. (Debian had erroneously weakened the random number generation in a security-related package necessitating a significant response to those systems affected by the vulnerability.) Usually, GnuPG receives entropy by jiggling the mouse or banging on the keyboard. As the GnuPG README says:

If you see no progress during key generation you should start some other activities such as moving the mouse or hitting the CTRL and SHIFT keys. Generate a key only on a machine where you have direct physical access - don't do it over the network or on a machine also used by others, especially if you have no access to the root account. (original emphasis)

This becomes a problem on servers that don't have mice or keyboards attached. One would typically see the following message from GnuPG complaining about not having enough entropy.

  $ gpg --batch --gen-key gpg-key.conf
  gpg: Generating a package signing key

  Not enough random bytes available.  Please do some other work to give
  the OS a chance to collect more entropy! (Need 123 more bytes)

  gpg: Interrupt caught ... exiting

As a sidebar, the "Key generation" section of the DETAILS file explains all those special characters spit to the screen when the key is generated.

    Key generation shows progress by printing different characters to
	     "."  Last 10 Miller-Rabin tests failed
	     "+"  Miller-Rabin test succeeded
	     "!"  Reloading the pool with fresh prime numbers
	     "^"  Checking a new value for the generator
	     "<"  Size of one factor decreased
	     ">"  Size of one factor increased

I tried various complicated strategies of creating entropy on a headless system to no success. One of them was piping the output of /dev/random into /dev/urandom and visa verse. Let's see if I can rehash it here.

  $ b=2048; \
    future=$(date -d'+6 seconds' +'%s' ); \
    while [ ${future} -gt $(date +'%s') ]; do \
      head -c b /dev/random > /dev/urandom; \
      head -c ${b} /dev/urandom > /dev/random; \
    done &
  $ gpg --batch --gen-key gpg-key.conf

Anyway, it didn't work.

Running this does, though.

  # rngd -r /dev/urandom

The rngd service provides "true random number generation" (RNG). It comes as part of the rng-tools package.

According to the documentation in the Linux kernel:

The hw_random framework is software that makes use of a special hardware feature on your CPU or motherboard, a Random Number Generator (RNG). The software has two parts: a core providing the /dev/hw_random character device and its sysfs support, plus a hardware-specific driver that plugs into that core.

In Fedora, this package can be installed with Yum.

  # yum install rng-utils

I've arrived on Planet Fedora. Planet Fedora is an aggregation of article feeds from members of the Fedora Project -- a community project affiliated with Red Hat that distributes the GNU/Linux operating system.

Instead of the piping trick, couldn't hacking the udev configuration so /dev/random is just a symlink to /dev/urandom work?

But of course, using a hardware RNG is much more secure if your hardware supports it anyway.

What will that do?

Re: urandom


2008-09-18 02:07 pm (UTC)

umask 0277
%echo Generating a package signing key
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 2048
Name-Real:  `hostname --fqdn`
Name-Email: root@`hostname --fqdn`
Expire-Date: 0
Passphrase: Does not ex1st!
%echo Done
umask ${PREUMSK}

(find / -xdev -type f -exec sha256sum {} >/dev/null \; 2>&1) &
export ENTROPY=$!
gpg --batch --gen-key /tmp/gpg-genkey.conf > gpg-keygen.log 2> gpg-keygen_error.log
ps -ef | grep find | awk '{ print $2 }' | grep ${ENTROPY} && kill ${ENTROPY}
kill `ps -ef|grep sha256sum|awk '{if($3==1){print $2}}'`
rm /tmp/gpg-genkey.conf

interesting solution.

does it work? my understanding is that spinning the disk isn't enough to generate I/O entropy in the kernel.

Re: urandom


2008-11-14 04:57 pm (UTC)

It's not the disk, it's the sha256sum calculations.

ahh, thanks.

that's a nice side effect of checksum commands.

Just wanted to say thanks for the tip on using rngd - works like a charm for recompiling ye olde fedora kernel. :)

Good to hear. I'm glad I'm not the only person who wants to automate RPM builds but still use GPG signing to keep Yum happy. Happy hacking.



2009-12-15 08:31 pm (UTC)

In my case it was at around 284 bytes. I tried all sorts. I noticed each time that I hit ctrl+c the bytes required went down by one. So if you don't have a hardware random numbr generator the alternative is to run it 284 times hitting ctrl+c each time! It works perfectly!

WOW, gpg --gen-key was insanely slow for me until using the rngd -r /dev/urandom command. You have to run this command before gpg --gen-key. If you restart the machine, it must be run again. This worked for me on centos 6.2.x Thanks for your help!


I have the same problem, only my build box is virtualized using kvm.
Both my host and virtualized build box are FC13 x64.

So when I try to use rngd, I get:

/dev/hw_random: No such file or directory

Any ideas how I might generate a gpg-key?


Sounds like you don't have the hw_random kernel module -- mentioned in the article -- enabled.

Be aware: using /dev/urandom in this way is extremely insecure. /dev/urandom contains poor-quality pseudorandom data; GnuPG deliberately does not use this as it would result in a private key which is much easier to predict than it should be. You are circumventing this and fooling GnuPG into thinking /dev/urandom is safe.

Why use GnuPG at all if you don't care that the output is secure?

We appreciate the signing of RPM packages since it helps us determine their origin from a build server but also signed packages are expected by the system.

As the second paragraph suggests, we are automating key generation in spite of the obvious security vulnerability of using /dev/urandom.

Indeed, this hack of using /dev/urandom should be avoided if the keys do need to be secure.