Add second sub-key to unattended GPG key

Solution 1:

Save for the year 2019, this how you do it in an ephemeral home directory:

export GNUPGHOME=$(mktemp -d)
gpg --batch --passphrase '' \
    --quick-generate-key "Firstname Lastname <[email protected]>" ed25519 cert 1y

FPR=$(gpg --list-options show-only-fpr-mbox --list-secret-keys | awk '{print $1}')

gpg --batch --passphrase '' \
    --quick-add-key $FPR ed25519 sign 1y
gpg --batch --passphrase '' \
    --quick-add-key $FPR cv25519 encrypt 1y

The trick is to use --quick-add-key.

An authentication subkey can be added similarly. We get:

$ gpg -K
/tmp/tmp.JSOrV6s0iL/pubring.kbx
-------------------------------
sec   ed25519 2019-04-11 [C] [expires: 2020-04-10]
      7E00D8318E2A2825F40981D00C6CA12AC7F293F3
uid           [ultimate] Firstname Lastname <[email protected]>
ssb   ed25519 2019-04-11 [S] [expires: 2020-04-10]
ssb   cv25519 2019-04-11 [E] [expires: 2020-04-10]

$ gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4

Solution 2:

To have gpg2 read your commands from stdin, use --command-fd=0. To have gpg2 read the passphrase of the master key from where it reads your commands from, use --pinentry-mode=loopback. (gpg2 --help does not list these switches, but they are documented in the man page.) Using these switches, you can communicate with gpg2 non-interactively.

I added a subkey to an existing master key by running bash commands similar to the following ones:

key=0123456789ABCDEF
passphrase="my passphrase"
{
    echo addkey
    echo 4     # RSA (sign only)
    echo 4096  # key length
    echo 0     # key does not expire
    echo y     # is this correct?
    echo y     # really create?
    echo "$passphrase"
    echo save
} | gpg2 --command-fd=0 --status-fd=1 --pinentry-mode=loopback --edit-key $key