Skip to content

Findings from exposing cas-lib 0.2.85 in the TypeScript SDK: Argon2 key derivation, ML-KEM dk validation, PBKDF2 doc #90

Description

@WingZer0o

Three findings from wiring cas-lib 0.2.85 into cas-typescript-sdk and validating it against Wycheproof vectors (cas-typescript-sdk#90):

1. CASArgon::derive_aes_128_key / derive_aes_256_key produce unreproducible keys

password_hashers/argon2.rs generates a random 16-byte salt inside the function and never returns it:

pub fn derive_aes_128_key(password: Vec<u8>) -> CasResult<Vec<u8>> {
    let mut rng = OsRng;
    let mut salt: [u8; 16] = [0; 16];
    rng.fill_bytes(&mut salt);
    ...
}

The caller can never re-derive the same key from the same password, which defeats the purpose of password-based key derivation (anything encrypted under the derived key is unrecoverable once the key leaves memory). Suggested fix: accept the salt as a parameter (like pbkdf2::derivation_with_salt) and/or return it alongside the key (like Pbkdf2Result). The TypeScript SDK is deliberately not exposing these two functions until this is fixed.

2. ML-KEM-1024 decapsulation skips the FIPS 203 decapsulation-key check

Wycheproof's mlkem_1024_semi_expanded_decaps_test.json tcId 6/7 (InvalidDecapsulationKey — corrupted embedded hash / embedded key) are expected to be rejected per FIPS 203 §7.3 input validation, but ml_kem_1024_decapsulate accepts them and returns a shared secret. Root cause: RustCrypto ml-kem's DecapsulationKey::from_bytes treats the key as trusted and performs no hash check. cas-lib could add the check itself (recompute H(ek) from the embedded encapsulation key and compare with the embedded hash) before decapsulating. The SDK's test suite currently documents this as a known deviation.

3. PBKDF2 doc comment says SHA-256 but the implementation is SHA3-256

password_hashers/pbkdf2.rs doc comments state "PBKDF2 with SHA-256", but the code uses pbkdf2_hmac_array::<Sha3_256, 32>. One or the other should change; note that switching the algorithm would break existing derived keys, so fixing the docs is the safer option. (This also means standard PBKDF2-HMAC-SHA256 test vectors, e.g. Wycheproof's, don't apply.)

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions