MultiRecipientHybrid from a KEM, an AEAD and a hash #
ENCAPSULATE(keys, payload):
for pk in keys: ct_i, ss_i := KEM_ENCAP(pk) -- independent per recipient
secret_i := HASH(ss_i)
msgKey := RANDOM(32)
envelope := nonce ‖ AEAD_seal(msgKey, payload)
dek_i := nonce_i ‖ AEAD_seal(secret_i, msgKey)
return [secret_i], ([ct_i], [dek_i], envelope)
DECAPSULATE(sk, ct): -- ct already filtered to one recipient
ss := KEM_DECAP(sk, ct.kemCiphertexts[0])
secret := HASH(ss)
msgKey := AEAD_open(secret, ct.deks[0])
return secret, AEAD_open(msgKey, ct.envelope)
The pure functions take explicit randomness (Rand); the instance draws it from a
KEM.Adapter.St seed stream, which must be unpredictable. Reliable requires KEM.Reliable for
every KEM seed the stream can yield.
The three primitives, and the fact that lets a hash output be an AEAD key.
- kem : KEM.KEM.KEM
- aead : Cipher.AEAD.AEAD
- hash : Hash.Hash.Hash
Instances For
The sender's randomness, with one KEM seed per recipient.
Instances For
A raw byte string as an AEAD key, if it is the right length.
Equations
Instances For
The derived key: the hashed KEM shared secret.
Equations
- S.deriveKeyBytes ss = Cryptlib.Util.Bytes.ofVector (S.hash.hash (Cryptlib.Util.Bytes.ofVector (S.kem.encodePlaintext ss)))
Instances For
The derived key as an AEAD.Key.
Equations
- S.deriveKeyAead ss = S.aead.keyFromBytes (Vector.cast ⋯ (S.hash.hash (Cryptlib.Util.Bytes.ofVector (S.kem.encodePlaintext ss))))
Instances For
Sealing under a key: nonce, then AEAD ciphertext #
kem.encap from a seed-derived state, none on error.
Equations
- S.encapPair pk seed = match S.kem.encap pk (S.kem.stateFromSeed seed) with | EStateM.Result.ok r a => some r | EStateM.Result.error a a_1 => none
Instances For
The construction, with explicit randomness #
Encrypt payload to every recipient. none if any recipient's KEM.encap fails.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Open a single-recipient ciphertext: decapsulate, open the DEK, then the envelope.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Unpack a successful encapsulation.
One KEM ciphertext, one nonce + key + tag-byte DEK and one derived key per recipient, and an
envelope nonce + tag longer than the payload.
If its KEM seed is Reliable, recipient i recovers the payload and its derived key from the
ciphertext carrying only its KEM ciphertext and DEK.
Replies #
Equations
- S.decryptEnvelopeP key envelope = do let k ← S.keyOfBytes key S.unsealUnder k envelope
Instances For
The MultiRecipientHybrid instance #
Randomness for encapsulating to n recipients, from stream position i: message key,
envelope nonce, then one DEK nonce and one KEM seed per recipient.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Every seed in the stream gives a Reliable KEM state.
Equations
- Cryptlib.Primitives.MultiRecipientHybrid.Adapter.Reliable S s = ∀ (j : Nat), S.kem.Reliable (S.kem.stateFromSeed (s.snd j))
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
MultiRecipientHybrid over the given KEM, AEAD and hash.
Equations
- One or more equations did not get rendered due to their size.
Instances For
MultiRecipientHybrid over a KEM, an AEAD, and a hash whose digest is an AEAD key.
Equations
- Cryptlib.Primitives.MultiRecipientHybrid.Adapter.hybridOfKEM kem aead hash h = Cryptlib.Primitives.MultiRecipientHybrid.Adapter.ofBase { kem := kem, aead := aead, hash := hash, digest_eq_key := h }