Skip to content

Cryptographic Suite

PlyQR implements AEAD (Authenticated Encryption with Associated Data) using ChaCha20-Poly1305 (RFC 8439) combined with BLAKE3 for key derivation and domain separation.


  • Cipher: ChaCha20 stream cipher with 256-bit key and 96-bit nonce.
  • Authentication Tag: Poly1305 128-bit (16-byte) one-time authenticator.
  • Key Derivation & Hashing: BLAKE3 cryptographic hash function in keyed and domain-separated KDF modes.

Each generated PlyQR code uses a unique 96-bit (12-byte) nonce:

$$\text{Nonce} = \text{nonce_prefix (6 bytes)} \parallel \text{derived_counter (6 bytes)}$$

  • nonce_prefix (48 bits): Generated from the system’s cryptographically secure pseudorandom number generator (OsRng) and embedded publicly in the 22-byte header.
  • derived_counter (48 bits): Computed via BLAKE3 domain separation over the master key, symbol dimensions, and public message hash.

This guarantees that re-encoding identical public and private messages produces visually distinct, uniquely keyed QR matrices without nonce reuse.


To prevent cut-and-paste or substitution attacks, the Poly1305 tag authenticates not only the private ciphertext but also the complete public environment via AAD:

$$\text{AAD} = \text{Header (22 bytes)} \parallel \text{Public Payload Bytes}$$

  1. Public Payload Binding: If an attacker modifies the public URL (e.g., redirecting to a phishing site), the AAD check fails, and the private data is rejected.
  2. Dimension Binding: Moving the private data to a different QR version, error correction level, or mask invalidates the authentication tag.
  3. Ciphertext Integrity: Any bit-flip or optical corruption in the encrypted codewords causes immediate authentication failure.