From 36b281af3eebedbe6ec45675c2c9f1b613c8859c Mon Sep 17 00:00:00 2001 From: laruizlo Date: Sun, 21 Jun 2026 16:41:37 -0400 Subject: [PATCH 1/4] test: closing hazardous operations during key material tests --- crypto/core/tests/key_material_tests.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/crypto/core/tests/key_material_tests.rs b/crypto/core/tests/key_material_tests.rs index 5e773fd..f55e771 100644 --- a/crypto/core/tests/key_material_tests.rs +++ b/crypto/core/tests/key_material_tests.rs @@ -65,7 +65,7 @@ mod test_key_material { key.allow_hazardous_operations(); key.set_bytes_as_type(&key_bytes, KeyType::BytesLowEntropy).unwrap(); assert_eq!(key.key_type(), KeyType::BytesLowEntropy); - + key.drop_hazardous_operations(); // nothing else requires setting hazardous operations. } @@ -94,6 +94,7 @@ mod test_key_material { key.set_key_len(32).unwrap(); assert_eq!(key.ref_to_bytes(), &[2u8; 32]); assert_eq!(key.key_len(), 32); + key.drop_hazardous_operations(); } #[test] @@ -182,6 +183,7 @@ mod test_key_material { let mut buf = vec![0u8; key_len]; buf.copy_from_slice(key.ref_to_bytes()); assert!(buf.iter().all(|&b| b == 0)); + key.drop_hazardous_operations(); } #[test] @@ -263,8 +265,8 @@ mod test_key_material { key.convert_key_type(KeyType::BytesFullEntropy).unwrap(); assert_eq!(key.key_type(), KeyType::BytesFullEntropy); assert!(key.is_full_entropy()); - key.drop_hazardous_operations(); + match key.convert_key_type(KeyType::SymmetricCipherKey) { Ok(()) => { /* good */ } _ => panic!("Expected Ok(())"), @@ -277,11 +279,12 @@ mod test_key_material { let mut key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); key.allow_hazardous_operations(); key.convert_key_type(KeyType::BytesFullEntropy).unwrap(); + key.drop_hazardous_operations(); match key.convert_key_type(KeyType::Seed) { Ok(()) => { /* good */ } _ => panic!("Expected Ok(())"), } - + // each KeyType can convert to itself let mut key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); @@ -406,18 +409,22 @@ mod test_key_material { key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); key.allow_hazardous_operations(); key.convert_key_type(KeyType::BytesFullEntropy).unwrap(); + key.drop_hazardous_operations(); key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); key.allow_hazardous_operations(); key.convert_key_type(KeyType::MACKey).unwrap(); + key.drop_hazardous_operations(); key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); key.allow_hazardous_operations(); key.convert_key_type(KeyType::SymmetricCipherKey).unwrap(); + key.drop_hazardous_operations(); key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); key.allow_hazardous_operations(); key.convert_key_type(KeyType::Seed).unwrap(); + key.drop_hazardous_operations(); } #[test] @@ -493,6 +500,7 @@ mod test_key_material { // should work if you allow hazardous conversions. key.allow_hazardous_operations(); key.convert_key_type(KeyType::SymmetricCipherKey).unwrap(); + key.drop_hazardous_operations(); } #[test] @@ -570,6 +578,7 @@ mod test_key_material { // now it should work key.set_security_strength(SecurityStrength::_128bit).unwrap(); assert_eq!(key.security_strength(), SecurityStrength::_128bit); + key.drop_hazardous_operations(); // BytesLowEntropy keys cannot have a security strength other than None. // success @@ -583,12 +592,14 @@ mod test_key_material { Err(KeyMaterialError::SecurityStrength(_)) => { /* good */ } _ => panic!("Expected KeyMaterialError::SecurityStrength"), } + key.drop_hazardous_operations(); // Zeroized keys cannot have a security strength other than None. // success let mut key = KeyMaterial256::new(); key.allow_hazardous_operations(); key.set_key_len(32).unwrap(); // still zeroized + key.drop_hazardous_operations(); assert_eq!(key.key_type(), KeyType::Zeroized); // setting to ::None should work .. even without setting .allow_hazardous_operations() key.set_security_strength(SecurityStrength::None).unwrap(); @@ -598,6 +609,7 @@ mod test_key_material { Err(KeyMaterialError::SecurityStrength(_)) => { /* good */ } _ => panic!("Expected KeyMaterialError::SecurityStrength"), } + key.drop_hazardous_operations(); } #[test] From 8d448b64a0b5a508867b4299630bd6a4be88911c Mon Sep 17 00:00:00 2001 From: laruizlo Date: Mon, 22 Jun 2026 07:40:42 -0400 Subject: [PATCH 2/4] test: making zeroize test inspect full key buffer --- crypto/core/tests/key_material_tests.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/crypto/core/tests/key_material_tests.rs b/crypto/core/tests/key_material_tests.rs index f55e771..b2996d9 100644 --- a/crypto/core/tests/key_material_tests.rs +++ b/crypto/core/tests/key_material_tests.rs @@ -174,15 +174,27 @@ mod test_key_material { #[test] fn zeroize() { let mut key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); + let capacity = key.capacity(); + + // Sanity check: the backing buffer actually holds non-zero key material before it is wiped. + // Without this, the post-zeroize assertion below could pass vacuously. + key.allow_hazardous_operations(); + assert!(key.mut_ref_to_bytes().unwrap().iter().any(|&b| b != 0)); + key.drop_hazardous_operations(); + key.zeroize(); let key_len = key.key_len(); - assert_eq!(key_len, 0); + assert_eq!(key_len4, 0); assert_eq!(key.key_type(), KeyType::Zeroized); + // zeroize() must wipe the entire backing buffer. + // Full capacity must be inspected to confirm the previously-set bytes were + // actually overwritten with zeros. + // Note: key_len is now 0, so ref_to_bytes() returns an empty slice. key.allow_hazardous_operations(); - let mut buf = vec![0u8; key_len]; - buf.copy_from_slice(key.ref_to_bytes()); - assert!(buf.iter().all(|&b| b == 0)); + let full_buf = key.mut_ref_to_bytes().unwrap(); + assert_eq!(full_buf.len(), capacity); + assert!(full_buf.iter().all(|&b| b == 0)); key.drop_hazardous_operations(); } From 34bf0dd9235a953ea1b7a38535ae68fa4597729a Mon Sep 17 00:00:00 2001 From: laruizlo Date: Mon, 22 Jun 2026 10:18:56 -0400 Subject: [PATCH 3/4] test: within bc-core, fix typo in zeroize and extend scope in eq --- crypto/core/tests/key_material_tests.rs | 55 ++++++++++++++++++------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/crypto/core/tests/key_material_tests.rs b/crypto/core/tests/key_material_tests.rs index b2996d9..50b83cb 100644 --- a/crypto/core/tests/key_material_tests.rs +++ b/crypto/core/tests/key_material_tests.rs @@ -184,7 +184,7 @@ mod test_key_material { key.zeroize(); let key_len = key.key_len(); - assert_eq!(key_len4, 0); + assert_eq!(key_len, 0); assert_eq!(key.key_type(), KeyType::Zeroized); // zeroize() must wipe the entire backing buffer. @@ -702,22 +702,49 @@ mod test_key_material { #[test] fn eq() { - // On instances of the same exact type (size). - let key1 = KeyMaterial256::from_bytes( - b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - ) - .unwrap(); - let key2 = KeyMaterial256::from_bytes( - b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", - ) - .unwrap(); + // For context: + // DUMMY_KEY: &[u8; 64] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ + // \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ + // \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ + // \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"; + + // Same bytes, full capacity. Should be equal. + let key1 = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); + let key2 = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); assert_eq!(key1, key2); - let key3 = KeyMaterial256::from_bytes( - b"\x0F\x0E\x0D\x0C\x0B\x0A\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00", - ) - .unwrap(); + // Same length, different content. Should NOT be equal. + let key3 = KeyMaterial256::from_bytes(&[0xFFu8; 32]).unwrap(); assert_ne!(key1, key3); + + // Different length, overlapping prefix. Should NOT be equal. + let key_short = KeyMaterial256::from_bytes(&DUMMY_KEY[..16]).unwrap(); + assert_ne!(key1, key_short); + + // PartialEq ignores key_type: same bytes, different KeyType. Should be equal. + let key_low = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesLowEntropy).unwrap(); + let key_mac = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::MACKey).unwrap(); + assert_eq!(key_low, key_mac); + + // PartialEq ignores security_strength: same bytes, different strength. Should be equal. + let key_strong = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy).unwrap(); + let mut key_weak = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy).unwrap(); + key_weak.set_security_strength(SecurityStrength::_128bit).unwrap(); + assert_ne!(key_strong.security_strength(), key_weak.security_strength()); // strengths differ + assert_eq!(key_strong, key_weak); // but keys are still equal + + // Partially-filled buffers with identical content. Should be equal. + let key_half1 = KeyMaterial256::from_bytes(&DUMMY_KEY[..16]).unwrap(); + let key_half2 = KeyMaterial256::from_bytes(&DUMMY_KEY[..16]).unwrap(); + assert_eq!(key_half1, key_half2); + + // Verify with a second size (KeyMaterial512) to cover the generic impl. + let key512_a = KeyMaterial512::from_bytes(&DUMMY_KEY[..64]).unwrap(); + let key512_b = KeyMaterial512::from_bytes(&DUMMY_KEY[..64]).unwrap(); + assert_eq!(key512_a, key512_b); + + let key512_c = KeyMaterial512::from_bytes(&[0xFFu8; 64]).unwrap(); + assert_ne!(key512_a, key512_c); } #[test] From 4f053af7a62429877c8e33777223c17136916f41 Mon Sep 17 00:00:00 2001 From: laruizlo Date: Mon, 22 Jun 2026 10:43:54 -0400 Subject: [PATCH 4/4] style: fix formatting issues --- crypto/core/tests/key_material_tests.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/crypto/core/tests/key_material_tests.rs b/crypto/core/tests/key_material_tests.rs index 50b83cb..95d2b6b 100644 --- a/crypto/core/tests/key_material_tests.rs +++ b/crypto/core/tests/key_material_tests.rs @@ -188,9 +188,9 @@ mod test_key_material { assert_eq!(key.key_type(), KeyType::Zeroized); // zeroize() must wipe the entire backing buffer. - // Full capacity must be inspected to confirm the previously-set bytes were + // Full capacity must be inspected to confirm the previously-set bytes were // actually overwritten with zeros. - // Note: key_len is now 0, so ref_to_bytes() returns an empty slice. + // Note: key_len is now 0, so ref_to_bytes() returns an empty slice. key.allow_hazardous_operations(); let full_buf = key.mut_ref_to_bytes().unwrap(); assert_eq!(full_buf.len(), capacity); @@ -296,7 +296,7 @@ mod test_key_material { Ok(()) => { /* good */ } _ => panic!("Expected Ok(())"), } - + // each KeyType can convert to itself let mut key = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); @@ -702,12 +702,12 @@ mod test_key_material { #[test] fn eq() { - // For context: + // For context: // DUMMY_KEY: &[u8; 64] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ // \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ // \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ // \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"; - + // Same bytes, full capacity. Should be equal. let key1 = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); let key2 = KeyMaterial256::from_bytes(&DUMMY_KEY[..32]).unwrap(); @@ -722,13 +722,19 @@ mod test_key_material { assert_ne!(key1, key_short); // PartialEq ignores key_type: same bytes, different KeyType. Should be equal. - let key_low = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesLowEntropy).unwrap(); - let key_mac = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::MACKey).unwrap(); + let key_low = + KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesLowEntropy).unwrap(); + let key_mac = + KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::MACKey).unwrap(); assert_eq!(key_low, key_mac); // PartialEq ignores security_strength: same bytes, different strength. Should be equal. - let key_strong = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy).unwrap(); - let mut key_weak = KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy).unwrap(); + let key_strong = + KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy) + .unwrap(); + let mut key_weak = + KeyMaterial256::from_bytes_as_type(&DUMMY_KEY[..32], KeyType::BytesFullEntropy) + .unwrap(); key_weak.set_security_strength(SecurityStrength::_128bit).unwrap(); assert_ne!(key_strong.security_strength(), key_weak.security_strength()); // strengths differ assert_eq!(key_strong, key_weak); // but keys are still equal