Skip to main content

Module crypto

Module crypto 

Source
Available on crate feature crypto only.
Expand description

SRT payload encryption — draft-sharabayko-srt-01 §6 (“Encryption”).

Spec grounding: specs/rules/srt-crypto.md (curated §6, external-algorithm references grep-verified against RFC 3394 / RFC 8018 / RFC 2104 / FIPS 197 / NIST SP 800-38A). Cross-refs: specs/rules/srt-rules.md §“Key Material message — §3.2.2” (wire layout of Salt/ICV/xSEK/oSEK/KLen, all carried opaquely by crate::packet::KeyMaterial) and §“Data packet — §3.1” (KK field, crate::packet::EncryptionKeyField).

This module adds the crypto primitives §6 names but does not restate:

  • AES-CTR payload encrypt/decrypt (aes_ctr_apply) — §6.2.2/§6.3.2.
  • RFC 3394 AES key wrap/unwrap of the SEK (wrap_sek/unwrap_sek) — §6.1.5/§6.2.1/§6.3.1.
  • PBKDF2 (HMAC-SHA1) KEK derivation from a passphrase (derive_kek) — §6.1.4/§6.2.1/§6.3.1.

Gated behind the crypto feature; the default/no_std packet-codec core (this crate’s --no-default-features build) pulls none of these dependencies.

§⚠ The draft’s two IV formulas (srt-crypto.md, “Conflicting IV formula”)

draft-sharabayko-srt-01 gives two different, unreconciled formulas for the AES-CTR IV:

  • §6.1.2 (Overview): build a 128-bit {80 zero bits | 32-bit packet index | 16-bit block counter} word and XOR its upper 112 bits with IV = MSB(112, Salt).
  • §6.2.2 (Encryption Process) / §6.3.2 (Decryption Process), verbatim and identical in both places: IV = (MSB(112, Salt) << 2) XOR (PktSeqNo).

These are not algebraically the same construction, and the draft never reconciles them. No sample ciphertext exists anywhere in the draft to disambiguate by reproduction (srt-crypto.md, “No test vectors” note), so this module resolves it against the reference implementation instead: libsrt (haivision/srt) haicrypt/hcrypt.h hcrypt_SetCtrIV builds the counter as §6.1.2 describes — {80 zero bits | 32-bit packet index | 16-bit block counter} with MSB(112, Salt) XORed across the top 112 bits — and performs no << 2 shift. The §6.2.2/§6.3.2 << 2 is a draft-text artifact; implementing it literally yields a keystream no real SRT peer can decrypt. packet_counter therefore follows hcrypt_SetCtrIV (≡ the §6.1.2 layout), verified byte-for-byte against that macro in the tests.

Constants§

PBKDF2_ITERATIONS
PBKDF2 iteration count mandated by the draft (Iter = 2048, §6.1.4/§6.2.1/§6.3.1 — identical value at every citation).
SALT_LEN
Length of the 128-bit Key Material Salt field in bytes (SLen/4 = 4 words — the only salt length the draft defines, srt-rules.md §3.2.2).

Functions§

aes_ctr_apply
AES-CTR encrypt/decrypt one data packet’s payload in place (draft-sharabayko-srt-01 §6.2.2/§6.3.2). CTR mode is its own inverse — EncryptedPayload = AES_CTR_Encrypt(SEK, IV, UnencryptedPayload) and DecryptedPayload = AES_CTR_Encrypt(SEK, IV, EncryptedPayload) are the same operation (XOR with the same keystream), so this one function serves both directions.
derive_kek
Derive the Key Encrypting Key (KEK) from the pre-shared passphrase (draft-sharabayko-srt-01 §6.1.4, §6.2.1 sender / §6.3.1 receiver — identical formula both sides):
packet_counter
Compute the 128-bit AES-CTR initial counter for one data packet.
select_sek
Select the SEK to use for a data packet from its KK field (draft-sharabayko-srt-01 §3.1/§6.1.6): even/odd are the two SEKs currently held (both may be live during the ±KM-Pre-Announcement-Period` rekey transition window, §6.1.6).
unwrap_sek
Unwrap the SEK(s) with the KEK (inverse RFC 3394 AES key wrap — draft-sharabayko-srt-01 §6.1.5/§6.3.1: SEK = AESkuw(KEK, Wrap)).
wrap_sek
Wrap one or two SEKs with the KEK (RFC 3394 AES key wrap, external algorithm — draft-sharabayko-srt-01 §6.1.5/§6.2.1: Wrap = AESkw(KEK, SEK)).