Hi,
I'm trying to add an existing ECDSA key as a signing subkey of an existing RSA key.
Unfortunately this doesn't work. Instead, gpg only wants to add the ECDSA key as an ECDH encrypting subkey instead.
I dug through the source code and figured out why this is:
- gpg send READKEY for the ECDSA keygrip to gpg-agent.
- gpg-agent returns something like this:
D (10:public-key(3:ecc(5:curve10:NIST P-256)(1:q ... )))
Notice in particular that there is no indication of whether this is an ECDSA key or an ECDH key, just that it is an ECC key.
- libgcrypt matches this key type using the ecc_names string array in cipher/ecc.c, and eventually maps it to GCRY_PK_ECC.
- this enum is converted by gnupg to the OpenPGP equivalent in map_gcry_pk_to_openpgp() in gnupg common/openpgp-oid.c:
switch (algo) { case GCRY_PK_EDDSA: return PUBKEY_ALGO_EDDSA; case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA; case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH; default: return algo < 110 ? (pubkey_algo_t)algo : 0; }
GCRY_PK_ECC falls through to the default case and its value is cast directly to pubkey_algo_t. The value of GCRY_PK_ECC is 18, which happens to match PUBKEY_ALGO_ECDH.
I hacked around this like so to produce an ECDSA subkey:
switch (algo) { case GCRY_PK_EDDSA: return PUBKEY_ALGO_EDDSA; case GCRY_PK_ECDSA: return PUBKEY_ALGO_ECDSA; case GCRY_PK_ECDH: return PUBKEY_ALGO_ECDH; + case GCRY_PK_ECC: return PUBKEY_ALGO_ECDSA; default: return algo < 110 ? (pubkey_algo_t)algo : 0; }
Of course this is just a dirty hack and not an actual proper fix.
Can we please get the option to use an ECC key as either an ECDH encrypting subkey, or an ECDSA signing subkey?
Cheers,
Scott.
Note: I tested this on my distro's versions (gnupg-2.2.27, libgcrypt-1.9.2), but the logic in question hasn't changed in gnupg-2.3.1.