Spqr.lean
Declarations on this page (57)
- inductive Direction
-
def Direction.
toByte -
def Direction.
flip - def encodeSpqrDirectionParams
- def spqrParamsDir?
- def encodeSpqrIndexTerm
- def zeroKey
- def spqrEmptyMsg
- structure SubF
- instance L81
- instance L82
-
def SubF.
length - structure SubF
- instance L91
- instance L92
-
def SubF.
length - structure SubF
- instance L100
- instance L101
-
def SubF.
length - structure SubF
- instance L109
- instance L110
-
def SubF.
length - structure SubF
- instance L118
- instance L119
-
def SubF.
length - structure SubF
- instance L127
- instance L128
-
def SubF.
length - structure SubF
- instance L136
- instance L137
-
def SubF.
length - #combine L141
-
abbrev InitState.
SubF. pack -
abbrev ChainKey.
SubF. pack -
abbrev SendState.
SubF. pack -
abbrev SendKey.
SubF. pack -
abbrev SendMsg.
SubF. pack -
abbrev RecvState.
SubF. pack -
abbrev RecvKey.
SubF. pack - def spqrInit
- def spqrChainKey
- def spqrSend
- def spqrRecv
-
def spqrInit.
attackerKnowledge -
def spqrChainKey.
attackerKnowledge -
def spqrStateArg.
attackerKnowledge -
def spqrSendState.
attackerKnowledge -
def spqrSendKey.
attackerKnowledge -
def spqrSendMsg.
attackerKnowledge -
def spqrRecvState.
attackerKnowledge -
def spqrRecvKey.
attackerKnowledge - #combine L251
SPQR V1 Post-Quantum Ratchet Equational Theory
DyLean term algebra, send/receive operations, and attacker deduction rules for the SPQR V1 ratchet. On fresh initial states (InitState), keys come from the epoch-0 chain (ChainKey) so honest first-message send and receive agree definitionally; subsequent transitions use opaque constructors (SendState, SendKey, SendMsg, RecvState, RecvKey).
namespace DY.Spqr@[expose] public section Directionsinductive Direction
Session direction (A_2_B = 0 for initiator Alice, B_2_A = 1 for responder Bob).
inductive Direction where
| a2b
| b2aend Directions@[expose] public section Literalsvariable [BytesFunctor] [BytesFunctor.Has Literal.SubF]open Literaldef encodeSpqrDirectionParams
Single-byte literal encoding the SPQR direction parameter.
def spqrParamsDir?
Decodes a direction from an encodeSpqrDirectionParams literal, returning none otherwise.
def encodeSpqrIndexTerm
4-byte little-endian literal encoding the u32 message index i.
def encodeSpqrIndexTerm (i: UInt32): Bytes :=
literalToBytes ⟨#[i.toUInt8, (i >>> 8).toUInt8, (i >>> 16).toUInt8, (i >>> 24).toUInt8]⟩def zeroKey
32-byte all-zero default HKDF salt returned at message index 0 on a fresh state.
def zeroKey: Bytes := literalToBytes ⟨Array.replicate 32 0⟩def spqrEmptyMsg
Whether msg is the empty literal (SPQR version 0, rejected by spqrRecv).
def spqrEmptyMsg (msg: Bytes): Bool :=
match bytesToLiteral msg with
| some b => b.size == 0
| none => falseend Literalsnamespace InitStatestructure SubF
public structure SubF (Bytes: Type) where
authKey: Bytes
params: Bytesinstance
public instance: ALaCarte.FunctorSizeOf SubF := .binary SubF.authKey SubF.paramsinstance
public instance: SubBytesFunctor SubF := .binary SubF.authKey SubF.params SubF.mk
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun ⟨a, b⟩ rec => rec a + rec bend InitStatenamespace ChainKeystructure SubF
public structure SubF (Bytes: Type) where
authKey: Bytes
params: Bytes
idx: Bytesinstance
public instance: ALaCarte.FunctorSizeOf SubF := .ternary SubF.authKey SubF.params SubF.idxinstance
public instance: SubBytesFunctor SubF := .ternary SubF.authKey SubF.params SubF.idx SubF.mk
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun _ _ => 32end ChainKeynamespace SendStatestructure SubF
public structure SubF (Bytes: Type) where
st: Bytes
coins: Bytesinstance
public instance: ALaCarte.FunctorSizeOf SubF := .binary SubF.st SubF.coinsinstance
public instance: SubBytesFunctor SubF := .binary SubF.st SubF.coins SubF.mk
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun ⟨a, b⟩ rec => rec a + rec bend SendStatenamespace SendKeystructure SubF
public structure SubF (Bytes: Type) where
st: Bytes
coins: Bytesinstance
public instance: ALaCarte.FunctorSizeOf SubF := .binary SubF.st SubF.coinsinstance
public instance: SubBytesFunctor SubF := .binary SubF.st SubF.coins SubF.mk
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun _ _ => 32end SendKeynamespace SendMsgstructure SubF
public structure SubF (Bytes: Type) where
st: Bytes
coins: Bytesinstance
public instance: ALaCarte.FunctorSizeOf SubF := .binary SubF.st SubF.coinsinstance
public instance: SubBytesFunctor SubF := .binary SubF.st SubF.coins SubF.mk
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun ⟨a, b⟩ rec => rec a + rec bend SendMsgnamespace RecvStatestructure SubF
public structure SubF (Bytes: Type) where
st: Bytes
msg: Bytes
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun ⟨a, b⟩ rec => rec a + rec bend RecvStatenamespace RecvKeystructure SubF
public structure SubF (Bytes: Type) where
st: Bytes
msg: Bytes
def SubF.
public def SubF.length [BytesFunctor]: Bytes.PartialLength SubF := fun _ _ => 32end RecvKey#combine
#combine into BytesFunctor, BytesLength from
InitState,
SendState,
SendKey,
SendMsg,
RecvState,
RecvKey,
ChainKey,@[expose] public section Constructorsvariable [BytesFunctor] [BytesFunctor.Has SubF]
abbrev InitState.
abbrev InitState.SubF.pack (x: InitState.SubF Bytes) := BytesView.pack x
abbrev ChainKey.
abbrev ChainKey.SubF.pack (x: ChainKey.SubF Bytes) := BytesView.pack x
abbrev SendState.
abbrev SendState.SubF.pack (x: SendState.SubF Bytes) := BytesView.pack x
abbrev SendKey.
abbrev SendKey.SubF.pack (x: SendKey.SubF Bytes) := BytesView.pack x
abbrev SendMsg.
abbrev SendMsg.SubF.pack (x: SendMsg.SubF Bytes) := BytesView.pack x
abbrev RecvState.
abbrev RecvState.SubF.pack (x: RecvState.SubF Bytes) := BytesView.pack x
abbrev RecvKey.
abbrev RecvKey.SubF.pack (x: RecvKey.SubF Bytes) := BytesView.pack xdef spqrInit
Initial SPQR state InitState{authKey, params}.
def spqrInit (authKey params: Bytes): Bytes :=
({authKey, params}: InitState.SubF Bytes).packdef spqrChainKey
Epoch-0 chain key at idx under authKey and params.
def spqrChainKey (authKey params idx: Bytes): Bytes :=
({authKey, params, idx}: ChainKey.SubF Bytes).packend Constructors@[expose] public section Functionsvariable [BytesFunctor] [BytesFunctor.Has SubF] [BytesFunctor.Has Literal.SubF]def spqrSend
SPQR send step returning (state', key, msg). On InitState{authKey, params} the key is spqrChainKey authKey params (encodeSpqrIndexTerm 1); otherwise it is SendKey{st, coins}.
def spqrSend (st coins: Bytes): Bytes × Bytes × Bytes :=
let key := match st.view? InitState.SubF with
| some ⟨authKey, params⟩ => spqrChainKey authKey params (encodeSpqrIndexTerm 1)
| none => ({st, coins}: SendKey.SubF Bytes).pack
(({st, coins}: SendState.SubF Bytes).pack, key, ({st, coins}: SendMsg.SubF Bytes).pack)def spqrRecv
SPQR receive step at message index idx returning some (state', key), or none on an empty message or malformed InitState parameters.
def spqrRecv (st msg: Bytes) (idx: UInt32): Option (Bytes × Bytes) :=
if spqrEmptyMsg msg then none
else
let st' := ({st, msg}: RecvState.SubF Bytes).pack
match st.view? InitState.SubF with
| some ⟨authKey, params⟩ =>
match spqrParamsDir? params with
| some dir =>
some (st', if idx = 0 then zeroKey
else spqrChainKey authKey (encodeSpqrDirectionParams dir.flip) (encodeSpqrIndexTerm idx))
| none => none
| none => some (st', ({st, msg}: RecvKey.SubF Bytes).pack)end Functionssection AttackerKnowledgeBuildvariable [BytesFunctor] [BytesFunctor.Has SubF]
def spqrInit.
@[expose] public
def spqrInit.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ authKey params, out = spqrInit authKey params ∧ p authKey ∧ p params
def spqrChainKey.
@[expose] public
def spqrChainKey.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out :=
∃ authKey params idx, out = spqrChainKey authKey params idx ∧ p authKey ∧ p params ∧ p idx
def spqrStateArg.
Projects arguments from a known SPQR state (InitState, SendState, or RecvState), modeling unencrypted pq_ratchet_state storage.
@[expose] public
def spqrStateArg.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out :=
(∃ x: InitState.SubF Bytes, p x.pack ∧ (out = x.authKey ∨ out = x.params)) ∨
(∃ x: SendState.SubF Bytes, p x.pack ∧ (out = x.st ∨ out = x.coins)) ∨
(∃ x: RecvState.SubF Bytes, p x.pack ∧ (out = x.st ∨ out = x.msg))end AttackerKnowledgeBuildsection AttackerKnowledgeRunvariable [BytesFunctor] [BytesFunctor.Has SubF] [BytesFunctor.Has Literal.SubF]
def spqrSendState.
@[expose] public
def spqrSendState.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ st coins, out = (spqrSend st coins).1 ∧ p st ∧ p coins
def spqrSendKey.
@[expose] public
def spqrSendKey.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ st coins, out = (spqrSend st coins).2.1 ∧ p st ∧ p coins
def spqrSendMsg.
@[expose] public
def spqrSendMsg.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ st coins, out = (spqrSend st coins).2.2 ∧ p st ∧ p coins
def spqrRecvState.
@[expose] public
def spqrRecvState.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ st msg idx r, spqrRecv st msg idx = some r ∧ out = r.1 ∧ p st ∧ p msg
def spqrRecvKey.
@[expose] public
def spqrRecvKey.attackerKnowledge: SubAttackerKnowledge SubF where
pred p out := ∃ st msg idx r, spqrRecv st msg idx = some r ∧ out = r.2 ∧ p st ∧ p msgend AttackerKnowledgeRun#combine
#combine [BytesFunctor.Has SubF] [BytesFunctor.Has Literal.SubF] into attackerKnowledge' from
spqrInit,
spqrChainKey,
spqrSendState,
spqrSendKey,
spqrSendMsg,
spqrRecvState,
spqrRecvKey,
spqrStateArg,end DY.Spqr