DEV Community

Cover image for PGP decryption and signing
conjurer
conjurer

Posted on

PGP decryption and signing

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

Pgp message structure

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

flow diagram

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.

streaming parser issue

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
Enter fullscreen mode Exit fullscreen mode

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)