Skip to main content

Post-Quantum Security

Platus implements hybrid encryption protocol BJJ-KEM1024, combining classical ECDH over Baby Jubjub with ML-KEM-1024 (FIPS 203) to provide post-quantum security for note encryption.

Hybrid Key Construction

Public Keys

The hybrid public key combines two components:

hPK=(ic,mPK)hPK = (ic, mPK)
  • ECC public key: ic=[vk]Gic = [vk]G
  • ML-KEM public key: mPK (1568 bytes, FIPS 203)mPK \text{ (1568 bytes, FIPS 203)}

Both are derived from the same spending public key via deterministic key derivation.

Private Keys

hSK=(vk,mSK)hSK = (vk, mSK)
  • ML-KEM secret key: mSK (3168 bytes)mSK \text{ (3168 bytes)}

Encryption Protocol

  1. Generate ephemeral ECDH keypair:

    rFrr \leftarrow \mathbb{F}_r R=[r]GR = [r]G
  2. Compute ECDH shared secret:

    Secdh=[r]icS_{ecdh} = [r] ic
  3. ML-KEM encapsulation:

    (Smlkem,ctmlkem)=ML-KEM-1024.Encapsulate(mPK)(S_\text{mlkem}, ct_\text{mlkem}) = \text{ML-KEM-1024.Encapsulate}(mPK)
  • Returns 32-byte shared secret SmlkemS_\text{mlkem} and 1568-byte ciphertext ctmlkemct_\text{mlkem}.
  1. Derive nonce:

    nonce_ikm=SecdhSmlkemnonce\_ikm = S_{ecdh} \,\|\, S_\text{mlkem} nonce=HKDF-Expand(HKDF-Extract(nonce_ikm),12)nonce = \text{HKDF-Expand}(\text{HKDF-Extract}(nonce\_ikm), 12)
  2. Authenticated encryption:

    plaintext=rmplaintext = r \,\|\, m ctaead=ChaCha20-Poly1305.Encrypt(key,nonce,plaintext)ct_{aead} = \text{ChaCha20-Poly1305.Encrypt}(key, nonce, plaintext)
  3. Output:

    ciphertext=ctmlkemctaeadciphertext = ct_{mlkem} \,\|\, ct_{aead} encapsulated_secret=Rencapsulated\_secret = R
  • Sizes:
    • ctmlkemct_{mlkem}: 1568 bytes
    • ctaeadct_{aead}: len(m)+32+16\text{len}(m) + 32 + 16 (message + ephemeral scalar + auth tag)
    • RR: 64 bytes

Decryption Protocol

Inputs

  • Ciphertext (ctmlkemct_{mlkem}, ctaeadct_{aead})
  • Encapsulated secret point ( R )
  • Receiver hybrid private key (vk{vk}, mSK{mSK})

Process

  1. Parse ciphertext

    ctmlkem=ciphertext[0:1568]ct_{mlkem} = ciphertext[0:1568] ctaead=ciphertext[1568:]ct_{aead} = ciphertext[1568:]
  2. Validate encapsulated secret

    R=BabyJubJub.fromBytesUnsafe(R)R' = \text{BabyJubJub.fromBytesUnsafe}(R)
  3. Compute ECDH shared secret

    Secdh=[vk]RS_{ecdh} = [{vk}]R'
  4. ML-KEM decapsulation

Smlkem={ML-KEM-1024.Decapsulate(ctmlkem,mSK),if valid032,if decapsulation failsS_{mlkem} = \begin{cases} \text{ML-KEM-1024.Decapsulate}(ct_{mlkem}, {mSK}), & \text{if valid} \\ 0^{32}, & \text{if decapsulation fails} \end{cases}
  1. Derive decryption key (same as encryption)
ikm=RSecdhSmlkemikm = R \,\|\, S_{ecdh} \,\|\, S_{mlkem} prk=HKDF-Extract(ikm)prk = \text{HKDF-Extract}(ikm) key=HKDF-Expand(prk,32)key = \text{HKDF-Expand}(prk, 32)
  1. Derive nonce and decrypt
nonce_ikm=SecdhSmlkemnonce\_ikm = S_{ecdh} \,\|\, S_{mlkem} nonce=HKDF-Expand(HKDF-Extract(nonce_ikm),12)nonce = \text{HKDF-Expand}(\text{HKDF-Extract}(nonce\_ikm), 12) plaintext=ChaCha20-Poly1305.Decrypt(key,nonce,ctaead)plaintext = \text{ChaCha20-Poly1305.Decrypt}(key, nonce, ct_{aead})
  1. Verify ephemeral secret
rm=plaintextr \,\|\, m = plaintext Rcheck=[r]GR_{check} = [r]G result={m,if Rcheck=Rnull,otherwise (invalid)\text{result} = \begin{cases} m, & \text{if } R_{\text{check}} = R' \\ \text{null}, & \text{otherwise (invalid)} \end{cases}

Threat Model

  • Classical adversary: Cannot break discrete log on Baby Jubjub.
  • Quantum adversary: Can break elliptic curve discrete log (Shor's algorithm) but cannot break lattice-based cryptography (ML-KEM).
  • Hybrid security: Notes remain secure if either ECDH or ML-KEM is unbroken. Both must fail for confidentiality to be compromised.