Status: accepted for the initial v0.1.0 implementation
Date: 2026-09-22
The initial public module exposes authenticated encryption for complete byte
slices through a root encryption package. It does not publish or retain the
old AES-CBC API, legacy ciphertext decoding, padding helpers, or a streaming
facade.
The module uses AES-256-GCM through Go's cipher.NewGCMWithRandomNonce. A
Box accepts one 32-byte random key, generates a new 96-bit nonce for every
message, and stores the nonce and authentication tag in a versioned envelope.
key := encryption.GenerateKey()
box, err := encryption.New(key)
envelope := box.Seal(plaintext, additionalData)
plaintext, err = box.Open(envelope, additionalData)Key persistence, distribution, rotation, passphrase derivation, KMS integration, and durable storage are application responsibilities.
offset size field
0 4 magic: "QBEN"
4 1 format version: 0x01
5 1 algorithm: 0x01 (AES-256-GCM with random nonce)
6 12 random GCM nonce
18 n ciphertext
18+n 16 GCM authentication tag
The six-byte header and caller-supplied additional data are authenticated as
AEAD additional data. Additional data is not stored in the envelope and must
be supplied byte-for-byte to Open.
All parse, compatibility, and authentication failures return one public
ErrInvalidEnvelope value and no plaintext. Unknown versions or algorithms
fail closed.
- Keys contain exactly 32 random bytes; passwords are not accepted as keys.
- A key must not seal more than 2^32 messages because random GCM nonces have a collision bound.
- The module does not provide streaming. A future streaming format would need independent nonce, ordering, truncation, and replay rules.
- The module does not attempt in-memory key zeroization, rollback protection, replay protection, or key lifecycle management.
- AES-CBC was rejected because the imported implementation was unauthenticated, deterministic under IV reuse, padding-ambiguous, and not a correct stream.
- Caller-managed nonces were rejected because nonce reuse is a severe and unnecessary API footgun for the intended use.
- Algorithm selection in the public API was rejected for
v0.1.0; the envelope identifier reserves explicit future format evolution without making cryptographic choice a caller responsibility.