25

I found in https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html#Unattended-GPG-key-generation method to generate gpg keys without user interaction, but it doesn't seem to work.

My script is:

#!/usr/bin/env bash
rm -rf .gnupg
mkdir -m 0700 .gnupg
touch .gnupg/gpg.conf
chmod 600 .gnupg/gpg.conf
tail -n +4 /usr/share/gnupg2/gpg-conf.skel > .gnupg/gpg.conf

touch .gnupg/{pub,sec}ring.gpg


cat >.gnupg/foo <<EOF
    %echo Generating a basic OpenPGP key
    Key-Type: RSA
    Key-Length: 2048
    Subkey-Type: RSA
    Subkey-Length: 2048
    Name-Real: User 1
    Name-Comment: User 1
    Name-Email: user@1.com
    Expire-Date: 0
    Passphrase: kljfhslfjkhsaljkhsdflgjkhsd
    %pubring foo.pub
    %secring foo.sec
    # Do a commit here, so that we can later print "done" :-)
    %commit
    %echo done
EOF

gpg2 --verbose --batch --gen-key .gnupg/foo

When I run it, it shows:

=$ ./gen.keys.sh 
gpg: Generating a basic OpenPGP key
gpg: no running gpg-agent - starting one
gpg: writing public key to `foo.pub'
gpg: writing secret key to `foo.sec'

But then it just hangs.

When I check, in the mean time, ps tree for this user, I see:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tstpg    22603  0.0  0.0  24108  5688 pts/9    Ss   14:59   0:00 -bash
tstpg    22624  0.0  0.0  13688  3168 pts/9    S+   14:59   0:00  \_ bash ./gen.keys.sh
tstpg    22632  0.2  0.0  27428  3676 pts/9    SL+  14:59   0:00      \_ gpg2 --verbose --batch --gen-key .gnupg/foo
tstpg    22634  0.3  0.0  18072  2884 pts/9    SL+  14:59   0:00          \_ gpg-agent --server

In ~/.gnupg/gpg.conf there is no mention about agent, and I have no idea what it's trying to do.

The foo.pub/foo.sec files are generated in home dir, but are empty.

What am I missing? How to generate the key without any kind of user interaction?

Versions:

  • gpg (GnuPG) 2.0.26
  • libgcrypt 1.6.2
eijeze
  • 457

4 Answers4

8

I found there are a few simple changes that make your script work. I have also included a few tests so that once the key is created it will automatically be tested.

Note that, unlike the code in the question, this key is not password protected.

#!/usr/bin/env bash
rm -rf .gnupg
mkdir -m 0700 .gnupg
touch .gnupg/gpg.conf
chmod 600 .gnupg/gpg.conf
tail -n +4 /usr/share/gnupg2/gpg-conf.skel > .gnupg/gpg.conf

cd .gnupg

I removed this line since these are created if a list key is done.

touch .gnupg/{pub,sec}ring.gpg

gpg2 --list-keys

cat >keydetails <<EOF %echo Generating a basic OpenPGP key Key-Type: RSA Key-Length: 2048 Subkey-Type: RSA Subkey-Length: 2048 Name-Real: User 1 Name-Comment: User 1 Name-Email: user@1.com Expire-Date: 0 %no-ask-passphrase %no-protection %pubring pubring.kbx %secring trustdb.gpg # Do a commit here, so that we can later print "done" :-) %commit %echo done EOF

gpg2 --verbose --batch --gen-key keydetails

Set trust to 5 for the key so we can encrypt without prompt.

echo -e "5\ny\n" | gpg2 --command-fd 0 --expert --edit-key user@1.com trust;

Test that the key was created and the permission the trust was set.

gpg2 --list-keys

Test the key can encrypt and decrypt.

gpg2 -e -a -r user@1.com keydetails

Delete the options and decrypt the original to stdout.

rm keydetails gpg2 -d keydetails.asc rm keydetails.asc

miken32
  • 1,021
wattry
  • 181
  • 1
  • 3
7

It is likely that you are running out of entropy. Key generation requires a lot of very high-quality random numbers; without the activity of the user to provide high-quality randomness to the computer, the entropy pool is being exhausted by generation, and the generation process just hangs, waiting for the pool to refill.

Your choices, in order of increasing satisfactoriness, are

  1. reconfiguring gpg to use the non-blocking pseudorandom number generator, which would be most unwise (though see below),

  2. using a software solution to derive more entropy from existing system state (the kernel is notoriously conservative about how much entropy it is prepared to derive from system state, particularly where that state has no direct human input, eg CPU or NIC timings); as you have pointed out, haveged is one such solution, or

  3. providing the computer with another physical source of high-grade entropy. Devices like the Entropy Key or the OneRNG can satisfy this requirement (I have no connection with either product save that I own an Entropy Key, and am very happy with it).

Edit: mzhaase draws my attention in a comment to this article on /dev/urandom vs. /dev/random (for which many thanks, it is an excellent article!) and takes issue with my dislike of using urandom to create keys. In fact, the article does not say that the two sources are equivalent, and notes that

Linux's /dev/urandom happily gives you not-so-random numbers before the kernel even had the chance to gather entropy. When is that? At system start, booting the computer.

That is to say that, after boot, until the urandom PRNG has been initialised with sufficient entropy, it really is unsafe to use it for key generation. That may take a while, especially on an unattended, headless server, and we don't know when the threshold has been reached, because the system doesn't explicitly tell us.

Now, if /dev/random is prepared to issue numbers I may reasonably infer that the entropy pool is deep enough that urandom will have been properly initialised. But if I have to check /dev/random for blocking before each use of urandom (which given that I generate keys less often than I reboot, is likely to be the case) I might as well just use the numbers from /dev/random to generate my keys.

MadHatter
  • 81,580
1

Worked this out as part of generating keys for an automated application install. Installing and starting the 'rngd' package to generate entroy will fix your issue. Simple to install and use.

Here's the code.

  • Starts rngd (/dev/hwrandom by default, but modifiable) to provide a source of entropy
  • Copies a simple template over (replace the jinja template email and name with what you want)
  • generates a key using gpg
  • imports it to the local keyring
xddsg
  • 3,540
-1

Here is one you could use but I would recommend running this script in a new terminal so as to not affect your current one. This script will continue to generate entropy by keeping the machine busy and stuck in an infinite loop until a user exits the script. No user interaction is necessary until after key generation. All the script does is list files forever.

It might take a few minutes (sometimes 10+) to generate depending on your machine and size of key but it is nice to not have to interact with it.

#!/bin/sh

while true;
do find * / && find * / && find * / && find * / && find * / && find * / && find * / && find * / && find * /;

echo "Press ctrl+c to exit this infinite loop"
sleep 2;
done
RalfFriedl
  • 3,258