1pub mod aead;
55pub mod agreement;
56pub mod digest;
57pub mod error;
58pub mod hkdf;
59pub mod hmac;
60pub mod rand;
61pub mod signature;
62pub(crate) mod spki;
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn sha256_digest_known_vector() {
70 let d = digest::digest(&digest::SHA256, b"");
72 assert_eq!(d.as_ref().len(), 32);
73 assert_eq!(
74 d.as_ref(),
75 &[
76 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f,
77 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
78 0x78, 0x52, 0xb8, 0x55,
79 ]
80 );
81 }
82
83 #[test]
84 fn sha256_digest_incremental() {
85 let mut ctx = digest::Context::new(&digest::SHA256);
86 ctx.update(b"abc");
87 let d = ctx.finish();
88 assert_eq!(
90 d.as_ref(),
91 &[
92 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae,
93 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61,
94 0xf2, 0x00, 0x15, 0xad,
95 ]
96 );
97 }
98
99 #[test]
100 fn hmac_sha256_sign_verify_roundtrip() {
101 let key = hmac::Key::new(hmac::HMAC_SHA256, b"my-secret-key");
102 let tag = hmac::sign(&key, b"hello world");
103 let result = hmac::verify(&key, b"hello world", tag.as_ref());
104 assert!(result.is_ok());
105 }
106
107 #[test]
108 fn hmac_sha256_wrong_data_rejected() {
109 let key = hmac::Key::new(hmac::HMAC_SHA256, b"my-secret-key");
110 let tag = hmac::sign(&key, b"hello world");
111 let result = hmac::verify(&key, b"hello WORLD", tag.as_ref());
112 assert!(result.is_err());
113 }
114
115 #[test]
116 fn hkdf_sha256_expand_known_length() {
117 struct Len32;
118 impl hkdf::KeyType for Len32 {
119 fn len(&self) -> usize {
120 32
121 }
122 }
123 let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, b"test-salt");
124 let prk = salt.extract(b"input-keying-material");
125 let mut out = [0u8; 32];
126 prk.expand(&[b"info"], Len32)
127 .unwrap()
128 .fill(&mut out)
129 .unwrap();
130 assert_ne!(out, [0u8; 32]);
131 }
132
133 #[test]
134 fn x25519_agreement_roundtrip() {
135 let rng = rand::SystemRandom::new();
136 let alice = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap();
137 let alice_pub = alice.compute_public_key().unwrap();
138
139 let bob = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap();
140 let bob_pub = bob.compute_public_key().unwrap();
141
142 let alice_secret = agreement::agree_ephemeral(
143 alice,
144 &agreement::UnparsedPublicKey::new(&agreement::X25519, bob_pub.as_ref()),
145 (),
146 |s| Ok::<Vec<u8>, ()>(s.to_vec()),
147 )
148 .unwrap();
149
150 let bob_secret = agreement::agree_ephemeral(
151 bob,
152 &agreement::UnparsedPublicKey::new(&agreement::X25519, alice_pub.as_ref()),
153 (),
154 |s| Ok::<Vec<u8>, ()>(s.to_vec()),
155 )
156 .unwrap();
157
158 assert_eq!(alice_secret, bob_secret);
159 assert!(!alice_secret.is_empty());
160 }
161
162 #[test]
163 fn aes_128_gcm_seal_open_roundtrip() {
164 let key_bytes = [0u8; 16];
165 let key = aead::UnboundKey::new(&aead::AES_128_GCM, &key_bytes).unwrap();
166 let lsk = aead::LessSafeKey::new(key);
167 let nonce = aead::Nonce::assume_unique_for_key([0u8; 12]);
168 let aad = aead::Aad::from(b"additional data".as_ref());
169
170 let plaintext = b"hello aead world!";
171 let mut in_out = plaintext.to_vec();
172 lsk.seal_in_place_append_tag(nonce, &aad, &mut in_out)
173 .unwrap();
174 assert!(in_out.len() > plaintext.len());
175
176 let nonce2 = aead::Nonce::assume_unique_for_key([0u8; 12]);
177 let aad2 = aead::Aad::from(b"additional data".as_ref());
178 let result = lsk.open_in_place(nonce2, &aad2, &mut in_out).unwrap();
179 assert_eq!(result, plaintext);
180 }
181
182 #[test]
183 fn ed25519_sign_verify() {
184 let keypair = signature::Ed25519KeyPair::generate().unwrap();
185 let msg = b"sign this message";
186 let sig = keypair.sign(msg).expect("Ed25519 sign failed");
187
188 let pub_key_bytes = keypair.public_key();
189 let result = signature::verify(&signature::ED25519, pub_key_bytes, msg, sig.as_ref());
190 assert!(result.is_ok(), "Ed25519 verification failed");
191 }
192
193 #[test]
194 fn aead_tampered_ciphertext_fails() {
195 let key = aead::UnboundKey::new(&aead::AES_128_GCM, &[0u8; 16]).unwrap();
196 let lsk = aead::LessSafeKey::new(key);
197 let mut in_out = b"secret".to_vec();
198 lsk.seal_in_place_append_tag(
199 aead::Nonce::assume_unique_for_key([0u8; 12]),
200 &aead::Aad::from(b"".as_ref()),
201 &mut in_out,
202 )
203 .unwrap();
204 in_out[0] ^= 0xff; assert!(lsk
206 .open_in_place(
207 aead::Nonce::assume_unique_for_key([0u8; 12]),
208 &aead::Aad::from(b"".as_ref()),
209 &mut in_out,
210 )
211 .is_err());
212 }
213
214 #[test]
215 fn ecdsa_wrong_key_verify_fails() {
216 let rng = rand::SystemRandom::new();
217 let kp1 = signature::EcdsaKeyPair::generate(&signature::ECDSA_P256_SHA256_ASN1).unwrap();
218 let kp2 = signature::EcdsaKeyPair::generate(&signature::ECDSA_P256_SHA256_ASN1).unwrap();
219 let msg = b"test message";
220 let sig = kp1.sign(&rng, msg).unwrap();
221 assert!(signature::verify(
222 &signature::ECDSA_P256_SHA256_ASN1,
223 kp2.public_key(),
224 msg,
225 sig.as_ref(),
226 )
227 .is_err());
228 }
229
230 #[test]
231 fn agreement_wrong_length_peer_key_fails() {
232 let rng = rand::SystemRandom::new();
233 let alice = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap();
234 let result = agreement::agree_ephemeral(
235 alice,
236 &agreement::UnparsedPublicKey::new(&agreement::X25519, &[0u8; 31]),
237 (),
238 |_| Ok::<(), ()>(()),
239 );
240 assert!(result.is_err());
241 }
242
243 #[test]
244 fn agreement_ec_compressed_point_rejected() {
245 let rng = rand::SystemRandom::new();
246 let alice = agreement::EphemeralPrivateKey::generate(&agreement::ECDH_P256, &rng).unwrap();
247 let mut bad = [0u8; 65];
248 bad[0] = 0x02; let result = agreement::agree_ephemeral(
250 alice,
251 &agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &bad),
252 (),
253 |_| Ok::<(), ()>(()),
254 );
255 assert!(result.is_err());
256 }
257}