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
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_keyproduce unreproducible keyspassword_hashers/argon2.rsgenerates a random 16-byte salt inside the function and never returns it: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 (likePbkdf2Result). 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.jsontcId 6/7 (InvalidDecapsulationKey— corrupted embedded hash / embedded key) are expected to be rejected per FIPS 203 §7.3 input validation, butml_kem_1024_decapsulateaccepts them and returns a shared secret. Root cause: RustCryptoml-kem'sDecapsulationKey::from_bytestreats the key as trusted and performs no hash check. cas-lib could add the check itself (recomputeH(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.rsdoc comments state "PBKDF2 with SHA-256", but the code usespbkdf2_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