Here's what we skip sometimes: when you receive an encrypted + signed PGP message, you can't see the signature until you decrypt it.
PGP signs first, then encrypts. The signature is sealed inside.
What's acTually insIde
The outer layer is encryption. Your private key unlocks it. Only then can you see:
- who signed it (signer's key id)
- actual content
- the sign itself
The 2 pHase floW
Decrypt -> reveals the signer's key id
Verify -> confirms the signature
The gotCha that cost me hoUrs
After decrypting, I tried parsing the content- extract the parts, do some processing, pass to verification.
Signature verification failed. Every time.
Here's why:
PGP libraries use streaming parsers. When you parse a packet, you get the header, but the body is still in the stream- waiting to be read. If you serialize what you parsed, the body is missing.
The fix:
Read raw bytes first, before parsing. Those bytes are the complete signed message. Pass them directly to verification.
Quik referEnce
Encrypted Message
├── Session Key (encrypted for you)
└── Encrypted Blob
└── [after decryption]
├── Signer's Key ID ← now you know who!
├── Content
└── Signature
FUrther reAding
RFC 4880 — The OpenPGP spec
gpg --list-packets — See any PGP message's structure
Sequoia PGP docs — If you're implementing in Rust



Top comments (0)