Let's say you verify someone's signature with GPG:

$ gpg --decrypt statement.txt.sig 
"I am not a crook."
gpg: Signature made 17 Nov 1973 9:31:50 AM CDT using RSA key ID 92861D99
gpg: Good signature from "Richard Nixon <rnixon@whitehouse.gov>"
gpg:                 aka "[jpeg image of size 19022]"

The statement.txt.sig file obviously includes the statement/data that is signed as well as the public key of the person who signed it. However, there is a lot more information included in the output, such as the full name and email address, as well as a JPEG image that was included with the public key of the signer.

Where is GPG getting that extra data from? Was it included in the file statement.txt.sig, or is it looking at your keyring and "filling in" all the extra details that you have on the person?


No, the information comes from the certificate kept in your public-key ring (or downloaded from a keyserver). The signature only contains some information needed to find the right certificate.

Use gpg --list-packets or pgpdump:

$ echo Foo. > foo.txt
$ gpg --detach-sign foo.txt
$ gpg --list-packets < foo.txt.sig
:signature packet: algo 1, keyid D24F6CB2C1B52632
    version 4, created 1410762670, md5len 0, sigclass 0x00
    digest algo 10, begin of digest 25 58
    hashed subpkt 2 len 4 (sig created 2014-09-15)
    subpkt 16 len 8 (issuer key ID D24F6CB2C1B52632)
    data: [4091 bits]

A detached signature has one "signature" packet, containing the algorithms, the signing timestamp, and the signer's 8-byte key ID, which is used to look up the signer's certificate in your keyring. (If you don't have any public keys with that keyid, GnuPG will attempt to find one in public keyservers.)

(I don't know why it has the key ID twice.)

GnuPG obtains everything about the signer by looking up the keyid – both the public key for actually verifying the signature, as well as the userid fields (name, address, photo) used to describe the signer.

Aside: Note that your example has a short 4-byte keyid, which is very bad as there have been a few hundred known short-keyid collisions, both intentional and accidental. Using keyid-format long in your ~/.gnupg/gnupg.conf would make it display longer keyids, though those are still easy to collide intentionally, so you should always check the fingerprint when importing a new key.

(The signature packets, however, always keep a 8-byte keyid inside. Some people configure GnuPG to put the fingerprint in a custom field (notation), but that's unfortunately not used by the software itself.)

Back to signatures. If you did gpg --list-packets on a regular (inline) signature, you'd see some more things:

:compressed packet: algo=1
:onepass_sig packet: keyid D24F6CB2C1B52632
    version 3, sigclass 0x00, digest 10, pubkey 1, last=1
:literal data packet:
    mode b (62), created 1410762587, name="",
    raw data: 5 bytes
:signature packet: algo 1, keyid D24F6CB2C1B52632
    version 4, created 1410762587, md5len 0, sigclass 0x00
    digest algo 10, begin of digest eb 31
    hashed subpkt 2 len 4 (sig created 2014-09-15)
    subpkt 16 len 8 (issuer key ID D24F6CB2C1B52632)
    data: [4095 bits]

The actual signed message is in the "literal data" packet, usually compressed using DEFLATE (pgpdump would show the actual algorithm being used).

It's preceded by a "onepass_sig" packet, whose only purpose is to provide the keyid without having to read until end of the whole message – so GnuPG can start searching for the keyid and proceed with verifying the message at once. (When reading from a pipe, e.g. cat|gpg, it is impossible to seek forwards and backwards; everything must be read in one pass.)

If you want, you can do this with the signer's key (certificate) as well. Just export it to a file first:

# gpg --export D24F6CB2C1B52632 | gpg --list-packets
:public key packet:
    version 4, algo 1, created 1256993643, expires 0
    pkey[0]: [4096 bits]
    pkey[1]: [17 bits]
    keyid: D24F6CB2C1B52632
:user ID packet: "Mantas Mikul\xc4\x97nas "
:signature packet: algo 1, keyid D24F6CB2C1B52632
    version 4, created 1256993643, md5len 0, sigclass 0x13
    digest algo 10, begin of digest 5a e2
[many more lines]

The certificates also consist ouf of packets, starting with a public key, userid's (text labels) with a self-signature for each (to protect against someone attaching fake userids to the pubkey), then several public subkey packets (again with self-signatures).

  • (I don't know why it has the key ID twice.) > Could it be showing up twice because you signed it with your master key? Perhaps it would list the issuer key ID as your master key, and keyid as the subkey if you had signed it with one? – IQAndreas Sep 20 '14 at 7:44
  • Nice theory, but I just checked and it's not a master cert/signing subkey thing (that's what my keys are like), the twing key IDs are whichever key made the signature. It'll be something to do with the subpacket it refers to in the signature packet, but I forget which bit of the RFC is relevant and I'm a little too tired to unearth it now (sorry). I can see how you drew that conclusion though, it does make some kinda sense. – Ben Jun 19 '15 at 9:38
  • 1
    From what I've read about the OpenPGP packet format recently, it simply makes less sense than X.509. Which says a lot about how little sense it makes. – grawity Jun 19 '15 at 12:42
  • I'm trying to verify GnuPG used the hash I specified with --s2k-digest-algo SHA256 (also see here). begin of digest eb 31 is pretty much useless. How can we determine the hash used when a detached signature is available? – jww Dec 28 '18 at 2:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.