Verify a certificate against GnuPG¶
Before publishing a certificate, check it with the implementation your
correspondents will actually use. A certificate that a Go parser accepts and
gpg rejects is a certificate nobody can send you anything with.
This is the same sequence the package's own interoperability tests run, so a failure here is a real problem rather than a local quirk.
Use a throwaway keyring¶
Never import an untested certificate into your real keyring — a bad import is tedious to unpick.
Everything below is scoped to that directory. When you are finished:
Killing the agent matters: it holds the directory open, and removing the home underneath a running agent leaves a confusing mess.
1. Import it¶
This is a stronger check than it looks. gpg validates self-signatures at
import and silently drops anything that does not verify — so a certificate
that imports with its subkey intact is one whose binding signature gpg checked
and accepted.
2. Confirm the subkey survived¶
The twelfth colon-separated field is the capability set. It must contain e
for encryption. If there is no sub line at all, the binding signature was
rejected and nothing can be encrypted to this certificate.
3. Check the signatures explicitly¶
The second field is ! for a signature that verified and - for one that did
not. Expect at least two ! — the self-certification and the subkey binding —
and no -.
4. Confirm your algorithm preferences took effect¶
This is the check most people skip, and the one that silently costs you security. The preferences live in the certification signature, so they can be read straight off the certificate:
Expect:
hashed subpkt 11 len 3 (pref-sym-algos: 9 8 7)
hashed subpkt 21 len 3 (pref-hash-algos: 10 9 8)
hashed subpkt 30 len 1 (features: 01)
9 8 7 is AES-256, AES-192, AES-128 — strongest first. features: 01 is the
request for integrity-protected encryption. If the pref-sym-algos line is
missing, senders fall back to AES-128 and every message you receive will be
weaker than your key allows, with no error to tell you.
Not
--list-packetson the message. The chosen cipher is inside the encrypted session key, so gpg cannot print it without the private key — which is the whole point of this design. Running it against a message showsNo secret keyand no algorithm. To see what a sender actually chose, decrypt the message:SessionKeyreturns the algorithm identifier alongside the key.
5. Round-trip a real message¶
Then open test.pgp with your key service — the
decrypt with AWS KMS guide has the code. Recovering
the plaintext is the only end-to-end proof, because the KDF binds the
certificate's fingerprint: assembly and decryption cannot be checked
independently. See
the fingerprint binding.
If gpg disagrees with Go¶
Believe gpg. It is what the other end of the exchange runs, and a certificate only has to satisfy the implementations that will actually read it.
Two independent Go implementations agreeing proves less than it appears to when one of them was written by reading the other — which is exactly why these tests exist alongside the differential ones.