MsgKeys.lean
Declarations on this page (16)
Hybrid Message-Key Derivation and Trace Helpers
Hybrid HKDF message-key derivation (trMsgKeys), protocol constants, and trace-inspection helpers shared by PQXDH and TripleRatchet.
namespace DY.Libsignal.TripleRatchet@[expose] public section MsgKeysvariable [BytesFunctor] [BytesLength] [BytesFunctor.Has Literal.SubF] [BytesFunctor.Has Concat.SubF]
[BytesFunctor.Has KdfExtract.SubF]open Literal Concat KdfExtractdef lit
def lit (s: String): Bytes := literalToBytes s.toUTF8def litByte
def litByte (b: UInt8): Bytes := literalToBytes ⟨#[b]⟩def hmac
HMAC-SHA256 (HKDF-Extract with salt = key, RFC 5869 §2.2).
def hmac (key msg: Bytes): Bytes := kdfExtract key msgdef hkdfBlock1
First three 32-byte RFC 5869 HKDF-Expand output blocks T(1), T(2), T(3) for SHA-256.
def hkdfBlock2
def hkdfBlock2 (prk info: Bytes): Bytes := hmac prk (concat (hkdfBlock1 prk info) (concat info (litByte 2)))def hkdfBlock3
def hkdfBlock3 (prk info: Bytes): Bytes := hmac prk (concat (hkdfBlock2 prk info) (concat info (litByte 3)))def zeroSalt
Default 32-byte all-zero HKDF salt (optional_salt = None, RFC 5869 §2.2).
def zeroSalt: Bytes := literalToBytes ⟨Array.replicate 32 0⟩structure MessageKeys
Output of MessageKeys::derive_keys.
structure MessageKeys where
cipherKey: Bytes
macKey: Bytes
/-- Full 32-byte third HKDF block; concretization uses its first 16 bytes as the AES-CBC IV. -/
iv: Bytesdef trMsgKeys
Hybrid message-key derivation MessageKeys::derive_keys(seed, Some(pqSalt), counter): expands "WhisperMessageKeys" from hmac pqSalt seed. When pqSalt = zeroSalt, this matches the unsalted optional_salt = None path.
def trMsgKeys (pqSalt seed: Bytes): MessageKeys :=
let prk := hmac pqSalt seed
{ cipherKey := hkdfBlock1 prk (lit "WhisperMessageKeys")
macKey := hkdfBlock2 prk (lit "WhisperMessageKeys")
iv := hkdfBlock3 prk (lit "WhisperMessageKeys") }def messageVersion
CIPHERTEXT_ (version 4).
def messageVersion: UInt8 := 4structure SignalMsg
Decoded SignalMessage fields together with the MAC-authenticated wire term and mac.
structure SignalMsg where
wire: Bytes
mac: Bytes
version: UInt8
ratchetKey: Bytes
counter: UInt32
ciphertext: Bytesdef maxForwardJumps
consts::MAX_FORWARD_JUMPS.
def maxForwardJumps: Nat := 25000def u32Max
u32::MAX (index + 1 overflows and aborts in libsignal).
def u32Max: UInt32 := 0xFFFFFFFFend MsgKeys@[expose] public section TraceHelpersdef anyEventOnTrace
Whether some EventT entry on tr satisfies p.
def anyEventOnTrace (EventT: Type) [ExecTraceTypes]
[ExecTraceTypes.Has (ProtocolEvent.ExecEntryT EventT)]
(tr: ExecTrace) (p: EventT → Bool) : Bool :=
(List.range tr.length).any fun i =>
match tr.getEventAt EventT i with
| some ev => p ev
| none => falsedef guardTrace
Trace guard that succeeds iff p tr holds, without appending to tr.
def guardTrace [ExecTraceTypes] (p: ExecTrace → Bool) : Traceful Unit :=
Traceful.mk fun tr => (if p tr then some () else none, ⟨tr, inst✝:ExecTraceTypesp:ExecTrace → Booltr:ExecTrace⊢ tr ≤ tr All goals completed! 🐙⟩)abbrev getStoredLocalStateAt?
Stored LocalState StateT at trace index idx, if any.
abbrev getStoredLocalStateAt? (StateT: Type) [ExecTraceTypes]
[ExecTraceTypes.Has (PersistentLocalState.State.ExecEntryT StateT)]
(tr: ExecTrace) (idx: Nat) : Option (PersistentLocalState.LocalState StateT) :=
((tr.at? idx : Option (PersistentGlobalState.State.ExecEntryT
(PersistentLocalState.LocalState StateT)))).map (·.st)end TraceHelpersend DY.Libsignal.TripleRatchet