14

I have a file secret.asc containing an ASCII-armored (i.e., plain text and starts with -----BEGIN PGP PRIVATE KEY BLOCK-----) PGP/GPG secret/private key, and I would like to know its 40-character key fingerprint without importing it into my GPG keyring. Unfortunately, not a single command I've tried has surrendered that information to me.

What I've Tried

The following failed attempts were run on Ubuntu Xenial 16.04.5 with gpg version 1.4.20 and gpg2 version 2.1.11. The key in question was created solely for experimentation purposes and won't be used in anything, so I don't care if the output reveals too much about it.

$ gpg --with-fingerprint secret.asc
sec  2048R/161722B3 2018-09-12 
uid                            Testing <testing@testing.nil>

Short key ID only, no fingerprint.

$ gpg2 --with-fingerprint secret.asc
gpg: DBG: FIXME: merging secret key blocks is not anymore available
gpg: DBG: FIXME: No way to print secret key packets here

Error.

$ gpg --with-fingerprint --no-default-keyring --secret-keyring ./secret.asc --list-secret-keys
gpg: [don't know]: invalid packet (ctb=2d)
gpg: keydb_search_first failed: invalid packet

Error.

$ gpg2 --with-fingerprint --no-default-keyring --secret-keyring ./secret.asc --list-secret-keys
/home/jwodder/.gnupg/pubring.gpg
--------------------------------
...

This lists the secret keys in my keyring for some reason.

$ gpg --dry-run --import -vvvv secret.asc
gpg: using character set `utf-8'
gpg: armor: BEGIN PGP PRIVATE KEY BLOCK
gpg: armor header: Version: GnuPG v1
:secret key packet:
        version 4, algo 1, created 1536783228, expires 0
        skey[0]: [2048 bits]
        skey[1]: [17 bits]
        skey[2]: [2047 bits]
        skey[3]: [1024 bits]
        skey[4]: [1024 bits]
        skey[5]: [1021 bits]
        checksum: 386f
        keyid: 07C0845B161722B3
:signature packet: algo 1, keyid 07C0845B161722B3
        version 4, created 1536783228, md5len 0, sigclass 0x1f
        digest algo 2, begin of digest b6 12
        hashed subpkt 2 len 4 (sig created 2018-09-12)
        hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=9F3C2033494B382BEF691BB403BB6744793721A3)
        hashed subpkt 7 len 1 (not revocable)
        subpkt 16 len 8 (issuer key ID 07C0845B161722B3)
        data: [2048 bits]
:user ID packet: "Testing <testing@testing.nil>"
:signature packet: algo 1, keyid 07C0845B161722B3
        version 4, created 1536783228, md5len 0, sigclass 0x13
        digest algo 2, begin of digest 33 ee
        hashed subpkt 2 len 4 (sig created 2018-09-12)
        hashed subpkt 27 len 1 (key flags: 03)
        hashed subpkt 9 len 4 (key expires after 32d3h46m)
        hashed subpkt 11 len 5 (pref-sym-algos: 9 8 7 3 2)
        hashed subpkt 21 len 5 (pref-hash-algos: 8 2 9 10 11)
        hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
        hashed subpkt 30 len 1 (features: 01)
        hashed subpkt 23 len 1 (key server preferences: 80)
        subpkt 16 len 8 (issuer key ID 07C0845B161722B3)
        data: [2046 bits]
gpg: sec  2048R/161722B3 2018-09-12   Testing <testing@testing.nil>
gpg: key 161722B3: secret key imported
gpg: pub  2048R/161722B3 2018-09-12  Testing <testing@testing.nil>
gpg: writing to `/home/jwodder/.gnupg/pubring.gpg'
gpg: using PGP trust model
gpg: key 793721A3: accepted as trusted key
gpg: key 161722B3: public key "[User ID not found]" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

The only fingerprint to be found is that of the revocation key.

$ gpg2 --dry-run --import -vvvv secret.asc

Same output as above.

$ gpg --list-packets secret.asc
$ gpg2 --list-packets secret.asc

Basically the same output as the --dry-run --import -vvvv commands, only without the gpg: lines.

jwodder
  • 448
  • I wasn't able to get it using GnuPG 2 either -- but using the old-stable GnupG 1.4 gpg1 --no-default-keyring --secret-keyring /tmp/a4ff2279.asc.gpg --with-fingerprint --list-secret-keys works out as expected. Seems like a mix of recent versions of GnupG merging the secret keyring into the public keyring (--secret-keyring ... is just ignored) and some weird behavior when listing keys where this change was forgotten. Might be a bug report candidate. – Jens Erat Sep 12 '18 at 21:34
  • @JensErat: That's my attempt #3; it just gives me an error. What version of gpg are you using? – jwodder Sep 12 '18 at 21:40
  • 1
    I forgot one minor but relevant detail: I dearmored the key first (gpg --dearmor). Was not able to get along with the armored copy, either. The ctd=2d error indicates issues with an unexpected -character -- probably the one starting or ending the key. – Jens Erat Sep 13 '18 at 19:10

3 Answers3

17

This probably changed with new versions of GnuPG as you can currently do this in one pipe:

$ gpg --with-colons --import-options show-only --import --fingerprint < secret.asc | awk -F: '$1 == "fpr" {print $10;}'

Main game changer is option import-options which enables fake import. We simply work with file as it would be imported but it is not.

Option --with-colons guarantee stable and machine-parseable format which we use in last awk part.

awk simply prints 10th column from line with fingerprint (one starting with fpr).

Kepi
  • 327
6

As indicated in the comments, the simplest solution appears to be to first dearmor the key and then run --list-secret-keys on the new file:

$ gpg --dearmor secret.asc  # Creates secret.asc.gpg
$ gpg --with-fingerprint --no-default-keyring --secret-keyring ./secret.asc.gpg --list-secret-keys

Annoyingly, although the dearmored key can be written to stdout with the -o - option, neither --secret-keyring - nor --secret-keyring /dev/stdin will allow the second command to read the key from stdin, so combining the two commands into one with a pipe isn't an option. Also, running the second command with gpg2 instead of gpg still fails to give the desired output.

A slightly more elaborate approach, but one that seems to work with both versions of gpg, is to import the secret key into a temporary GPG home directory and then list the temp home's private keys:

$ mkdir -m 0700 tmphome
$ gpg --homedir tmphome --import secret.asc
$ gpg --homedir tmphome --with-fingerprint --list-secret-keys
jwodder
  • 448
  • 1
    Your second solution does work for me. The first does not. It will always fall back to the default key ring even when --no-default-keyring is specified. The man page of gpg states Note that GnuPG will not operate without any keyrings, so if you use this option and do not provide alternate keyrings via --keyring or --secret-keyring, then GnuPG will still use the default public or secret keyrings. – Klaas Jan 16 '19 at 17:35
5

Since gpg 2.2.8 (released mid-2018) there is an option --show-keys for showing keys without importing them, provided as a shortcut for --import --import-options show-only.

To show the key(s) in the file secret.asc:

$ gpg --show-keys secret.asc

Different fingerprint format:

$ gpg --show-keys --with-fingerprint secret.asc
user_
  • 65