Page MenuHome GnuPG

Imported ECC/Ed25519 subkey has unusable key file in private-keys-v1.d
Open, LowPublic

Description

A batch-generated key with "Subkey-Type: ECC" and "Subkey-Curve: Ed25519" is created without errors and functions normally. But exporting and sebsequently importing the secret keys will create a secret subkey file in ~/.gnupg/private-keys-v1.d that does not match the subkey's keygrip.

Create the key:

$ gpg --batch --gen-key <<EOF
> Key-Type: default
> Subkey-Type: ECC
> Subkey-Curve: Ed25519
> Name-Real: testkey
> EOF
gpg: key 7FB1DD2949B22886 marked as ultimately trusted
gpg: revocation certificate stored as '/home/me/.gnupg/openpgp-revocs.d/2888D5166A0B5B72F361EDE97FB1DD2949B22886.rev'

List secret keys

$ gpg -K --with-keygrip
/home/me/.gnupg/pubring.kbx
-----------------------------
sec   rsa3072 2021-04-19 [SC]
      2888D5166A0B5B72F361EDE97FB1DD2949B22886
      Keygrip = 14B516BD5CA269B6B29FA59732BB600BEC85170D
uid           [ultimate] testkey
ssb   ed25519 2021-04-19 [E]
      Keygrip = 9673B76A5DC65B87B3F9C7E9F0BDAE37C2B9A59B

Everything about the key thus generated works fine - signing, verifying, encrypting, and decrypting. Problems only manifest when the secret keys are imported via --import-secret-keys. Also note that gpg set the subkey usage to Encryption despite it not being explicitly stated in the batch parameters.

The problem:

$ gpg -ao testkey --export-secret-keys 2888D5166A0B5B72F361EDE97FB1DD2949B22886
$ gpg --yes --delete-secret-and-public-keys 2888D5166A0B5B72F361EDE97FB1DD2949B22886
$ gpg --import testkey
$ gpg -K --with-keygrip
/home/me/.gnupg/pubring.kbx
-----------------------------
sec   rsa3072 2021-04-19 [SC]
      2888D5166A0B5B72F361EDE97FB1DD2949B22886
      Keygrip = 14B516BD5CA269B6B29FA59732BB600BEC85170D
uid           [ unknown] testkey
ssb#  ed25519 2021-04-19 [E]
      Keygrip = 9673B76A5DC65B87B3F9C7E9F0BDAE37C2B9A59B

The secret subkey is now unavailable.

Examining the contents of private-keys-v1.d:

$ ls ~/.gnupg/private-keys-v1.d
14B516BD5CA269B6B29FA59732BB600BEC85170D.key  330AEBFAE288A6B04B153E27088BEF1621BF0A8A.key

The only difference (besides the file name) is the file created by importing the secret subkey is 170 bytes and contains "(5:flags5:eddsa)", whereas the secret subkey file created by key generation is 150 bytes and does not contain this text. If the added text is removed and the file renamed to match the keygrip, the secret subkey once again works.

$ sed 's/(5:flags5:eddsa)//g' ~/.gnupg/private-keys-v1.d/330AEBFAE288A6B04B153E27088BEF1621BF0A8A.key > ~/.gnupg/private-keys-v1.d/9673B76A5DC65B87B3F9C7E9F0BDAE37C2B9A59B.key
$ gpg -K --with-keygrip
/home/me/.gnupg/pubring.kbx
-----------------------------
sec   rsa3072 2021-04-19 [SC]
      2888D5166A0B5B72F361EDE97FB1DD2949B22886
      Keygrip = 14B516BD5CA269B6B29FA59732BB600BEC85170D
uid           [ultimate] testkey
ssb   ed25519 2021-04-19 [E]
      Keygrip = 9673B76A5DC65B87B3F9C7E9F0BDAE37C2B9A59B

All is well again and the key functions normally.

Expected behavior is either throw an error during key generation or else create the private subkey files the same way from key generation and import.

Details

Version
2.2.27

Event Timeline

werner added a subscriber: werner.

You can't use an EdDSA as subkey for encryption. Encryption is the default for a subkey unless you provide key usage parameters. Yes, we could flag this as an error, but I won't give it high priority. I would anyway suggest to use

gpg --batch --quick-gen-key testkey

instead. This generates a standard key using ed25519/cv25519. Have a look at all the --quick functions they are far easier to use than the parameter thing.

You can't use an EdDSA as subkey for encryption. Encryption is the default for a subkey unless you provide key usage parameters. Yes, we could flag this as an error, but I won't give it high priority.

Yes, this is an edge case very unlikely to be encountered. The odd thing is the generated "ed25519" subkey does somehow encrypt and decrypt without issue.

I've run into a variant of this, too. If I generate they key just using (genkey (ecc (curve "Ed25519"))), it is recognized as an encryption key. One needs to use (genkey (ecc (curve "Ed25519")(flags eddsa))).

Needs to be checked for 2.4 - no backport to 2.2, though.