matter-crypto
Matter protocol session-establishment primitives — PASE (Password Authenticated Session Establishment) via SPAKE2+ and CASE (Certificate Authenticated Session Establishment) via SIGMA-I. Part of the matter-rust workspace.
Scope
PASE — spec §3.10
- Sans-IO state machines (
PaseProver,PaseVerifier) — drive bytes through method-per-message-type APIs; caller owns the transport. - SPAKE2+ math over P-256 with Matter's M and N constants.
- PBKDF2 setup-PIN derivation; HKDF session-key derivation.
- Constant-time confirmation tag comparison via
subtle. - Byte-for-byte verified against matter.js for three handshake scenarios (negotiation, known-params, max-iterations).
CASE — spec §4.13
- Sans-IO
CaseInitiator/CaseResponderstate machines. - SIGMA-I math: ephemeral P-256 ECDH, mutual ECDSA signatures, AES-CCM-128 encrypted blobs.
- NOC chain validation via
matter-cert::CertificateChain::validate. - Pluggable signing via the
CaseSignertrait — wire your own HSM/TPM/secure-element by implementing one method. - Session resumption: Sigma1 + Sigma2_Resume fast path. The caller
drives record lookup via the
Sigma1Outcomeenum (sans-IO purity). - Byte-for-byte verified against matter.js for the new-session scenario.
Resumption byte-parity is deferred — see
TODO-1.0.md.
Status
0.2.0. PASE and CASE feature-complete.
Minimal example
use ;
let pin = 20202021_u32;
let params = PasePbkdfParams ;
let mut prover = new_with_negotiation?;
let mut verifier = new_from_pin?;
// Drive the 5-message handshake — pseudo-code; caller pipes bytes
// between the two sides over the actual network in production.
let m = prover.start?;
verifier.handle_pbkdf_request?;
let m = verifier.next_message?;
prover.handle_pbkdf_response?;
let m = prover.next_message?;
verifier.handle_pake1?;
let m = verifier.next_message?;
prover.handle_pake2?;
let m = prover.next_message?;
verifier.handle_pake3?;
let prover_keys = prover.finish?;
let verifier_keys = verifier.finish?;
assert_eq!;
Minimal example — CASE
use ;
use TrustedRoots;
// --- Build credentials (caller supplies these) ---
// `noc` and `icac` are MatterCertificate values from matter-cert.
// `signer` holds the NOC private key.
let = generate?;
let rcac_pub: = *signer.public_key.as_bytes; // example; real app uses RCAC pub key
let initiator_creds = CaseCredentials ;
// --- Drive the 3-message Sigma1/2/3 handshake ---
// (caller pipes bytes across the network in a real deployment)
let mut initiator = new?;
let mut responder = new?;
let sigma1 = initiator.start?;
let outcome = responder.handle_sigma1?;
assert!;
let sigma2 = responder.next_message?;
initiator.handle_sigma2?;
let sigma3 = initiator.next_message?;
responder.handle_sigma3?;
let init_out = initiator.finish?;
let resp_out = responder.finish?;
// Both sides derive the same session keys.
assert_eq!;
Cryptographic primitives
This crate never implements crypto primitives. Underlying math:
ring— SHA-256, HMAC, HKDF, PBKDF2, ECDSA-verify.p256— P-256 scalar/point arithmetic for SPAKE2+ (ring deliberately doesn't expose these).subtle— constant-time comparison for PASE confirmation tags.aes+ccm— AES-CCM-128 for CASE encrypted blobs (ring 0.17 does not expose AES-CCM).
Cross-verification
PASE messages produced by our PaseProver and PaseVerifier are
byte-identical to matter.js's output for the same inputs. CI runs
this verification on every PR against three captured handshake
scenarios.
CASE new-session messages (Sigma1/2/3) are byte-identical to matter.js's
output for the same inputs. Resumption byte-parity is deferred —
known divergences are documented in TODO-1.0.md.
License
Apache 2.0. See LICENSE.