1use std::sync::atomic::{AtomicU64, Ordering};
19
20use bytes::Bytes;
21use zeroize::{Zeroize, ZeroizeOnDrop};
22
23use super::{AuthProtocol, PrivProtocol};
24use crate::error::{CryptoErrorKind, Error, Result};
25
26#[derive(Clone, Zeroize, ZeroizeOnDrop)]
38pub struct PrivKey {
39 key: Vec<u8>,
41 #[zeroize(skip)]
43 protocol: PrivProtocol,
44 #[zeroize(skip)]
47 salt_counter: u64,
48}
49
50pub struct SaltCounter(AtomicU64);
52
53impl SaltCounter {
54 pub fn new() -> Self {
56 let init = std::time::SystemTime::now()
58 .duration_since(std::time::UNIX_EPOCH)
59 .map(|d| d.as_nanos() as u64)
60 .unwrap_or(0);
61 Self(AtomicU64::new(init))
62 }
63
64 pub fn next(&self) -> u64 {
66 self.0.fetch_add(1, Ordering::SeqCst)
67 }
68}
69
70impl Default for SaltCounter {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl PrivKey {
77 pub fn from_password(
104 auth_protocol: AuthProtocol,
105 priv_protocol: PrivProtocol,
106 password: &[u8],
107 engine_id: &[u8],
108 ) -> Self {
109 use super::MasterKey;
110
111 let master = MasterKey::from_password(auth_protocol, password);
112 Self::from_master_key(&master, priv_protocol, engine_id)
113 }
114
115 pub fn from_master_key(
125 master: &super::MasterKey,
126 priv_protocol: PrivProtocol,
127 engine_id: &[u8],
128 ) -> Self {
129 let auth_protocol = master.protocol();
130
131 if !auth_protocol.is_compatible_with(priv_protocol) {
133 tracing::warn!(
134 auth_protocol = ?auth_protocol,
135 priv_protocol = ?priv_protocol,
136 auth_key_len = auth_protocol.digest_len(),
137 required_key_len = priv_protocol.key_len(),
138 "authentication protocol produces insufficient key material for privacy protocol; \
139 use SHA-224+ for AES-192, SHA-256+ for AES-256"
140 );
141 }
142
143 let localized = master.localize(engine_id);
145 let key = localized.as_bytes().to_vec();
146
147 Self {
148 key,
149 protocol: priv_protocol,
150 salt_counter: Self::init_salt(),
151 }
152 }
153
154 pub fn from_bytes(protocol: PrivProtocol, key: impl Into<Vec<u8>>) -> Self {
156 Self {
157 key: key.into(),
158 protocol,
159 salt_counter: Self::init_salt(),
160 }
161 }
162
163 fn init_salt() -> u64 {
165 std::time::SystemTime::now()
166 .duration_since(std::time::UNIX_EPOCH)
167 .map(|d| d.as_nanos() as u64)
168 .unwrap_or(0)
169 }
170
171 pub fn protocol(&self) -> PrivProtocol {
173 self.protocol
174 }
175
176 pub fn encryption_key(&self) -> &[u8] {
178 match self.protocol {
179 PrivProtocol::Des => &self.key[..8],
180 PrivProtocol::Aes128 => &self.key[..16],
181 PrivProtocol::Aes192 => &self.key[..24],
182 PrivProtocol::Aes256 => &self.key[..32],
183 }
184 }
185
186 pub fn encrypt(
198 &mut self,
199 plaintext: &[u8],
200 engine_boots: u32,
201 engine_time: u32,
202 salt_counter: Option<&SaltCounter>,
203 ) -> Result<(Bytes, Bytes)> {
204 let salt = salt_counter.map(|c| c.next()).unwrap_or_else(|| {
205 let s = self.salt_counter;
206 self.salt_counter = self.salt_counter.wrapping_add(1);
207 s
208 });
209
210 match self.protocol {
211 PrivProtocol::Des => self.encrypt_des(plaintext, engine_boots, salt),
212 PrivProtocol::Aes128 => {
213 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 16)
214 }
215 PrivProtocol::Aes192 => {
216 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 24)
217 }
218 PrivProtocol::Aes256 => {
219 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 32)
220 }
221 }
222 }
223
224 pub fn decrypt(
236 &self,
237 ciphertext: &[u8],
238 engine_boots: u32,
239 engine_time: u32,
240 priv_params: &[u8],
241 ) -> Result<Bytes> {
242 if priv_params.len() != 8 {
243 return Err(Error::decrypt(
244 None,
245 CryptoErrorKind::InvalidPrivParamsLength {
246 expected: 8,
247 actual: priv_params.len(),
248 },
249 ));
250 }
251
252 match self.protocol {
253 PrivProtocol::Des => self.decrypt_des(ciphertext, priv_params),
254 PrivProtocol::Aes128 | PrivProtocol::Aes192 | PrivProtocol::Aes256 => {
255 self.decrypt_aes(ciphertext, engine_boots, engine_time, priv_params)
256 }
257 }
258 }
259
260 fn encrypt_des(
262 &self,
263 plaintext: &[u8],
264 engine_boots: u32,
265 salt_int: u64,
266 ) -> Result<(Bytes, Bytes)> {
267 use cbc::cipher::{BlockEncryptMut, KeyIvInit};
268 type DesCbc = cbc::Encryptor<des::Des>;
269
270 let key = &self.key[..8];
272 let pre_iv = &self.key[8..16];
274
275 let mut salt = [0u8; 8];
278 salt[..4].copy_from_slice(&engine_boots.to_be_bytes());
279 salt[4..].copy_from_slice(&(salt_int as u32).to_be_bytes());
280
281 let mut iv = [0u8; 8];
283 for i in 0..8 {
284 iv[i] = pre_iv[i] ^ salt[i];
285 }
286
287 let pad_len = (8 - (plaintext.len() % 8)) % 8;
289 let padded_len = plaintext.len() + if pad_len == 0 { 0 } else { pad_len };
290 let padded_len = if padded_len == plaintext.len() && !plaintext.len().is_multiple_of(8) {
292 plaintext.len() + (8 - plaintext.len() % 8)
293 } else {
294 padded_len
295 };
296
297 let mut buffer = vec![
298 0u8;
299 if padded_len > plaintext.len() {
300 padded_len
301 } else {
302 plaintext.len() + 8 - (plaintext.len() % 8)
303 }
304 ];
305 let padded_len = buffer.len();
306 buffer[..plaintext.len()].copy_from_slice(plaintext);
307
308 let cipher = DesCbc::new_from_slices(key, &iv)
310 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
311
312 let ciphertext = cipher
313 .encrypt_padded_mut::<cbc::cipher::block_padding::NoPadding>(&mut buffer, padded_len)
314 .map_err(|_| Error::encrypt(None, CryptoErrorKind::CipherError))?;
315
316 Ok((
317 Bytes::copy_from_slice(ciphertext),
318 Bytes::copy_from_slice(&salt),
319 ))
320 }
321
322 fn decrypt_des(&self, ciphertext: &[u8], priv_params: &[u8]) -> Result<Bytes> {
324 use cbc::cipher::{BlockDecryptMut, KeyIvInit};
325 type DesCbc = cbc::Decryptor<des::Des>;
326
327 if !ciphertext.len().is_multiple_of(8) {
328 return Err(Error::decrypt(
329 None,
330 CryptoErrorKind::InvalidCiphertextLength {
331 length: ciphertext.len(),
332 block_size: 8,
333 },
334 ));
335 }
336
337 let key = &self.key[..8];
339 let pre_iv = &self.key[8..16];
341
342 let salt = priv_params;
344
345 let mut iv = [0u8; 8];
347 for i in 0..8 {
348 iv[i] = pre_iv[i] ^ salt[i];
349 }
350
351 let cipher = DesCbc::new_from_slices(key, &iv)
353 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
354
355 let mut buffer = ciphertext.to_vec();
356 let plaintext = cipher
357 .decrypt_padded_mut::<cbc::cipher::block_padding::NoPadding>(&mut buffer)
358 .map_err(|_| Error::decrypt(None, CryptoErrorKind::CipherError))?;
359
360 Ok(Bytes::copy_from_slice(plaintext))
361 }
362
363 fn encrypt_aes(
365 &self,
366 plaintext: &[u8],
367 engine_boots: u32,
368 engine_time: u32,
369 salt: u64,
370 key_len: usize,
371 ) -> Result<(Bytes, Bytes)> {
372 use aes::{Aes128, Aes192, Aes256};
373 use cfb_mode::cipher::{AsyncStreamCipher, KeyIvInit};
374
375 let key = &self.key[..key_len];
377
378 let salt_bytes = salt.to_be_bytes();
380
381 let mut iv = [0u8; 16];
384 iv[..4].copy_from_slice(&engine_boots.to_be_bytes());
385 iv[4..8].copy_from_slice(&engine_time.to_be_bytes());
386 iv[8..].copy_from_slice(&salt_bytes);
387
388 let mut buffer = plaintext.to_vec();
389
390 match key_len {
391 16 => {
392 type Aes128Cfb = cfb_mode::Encryptor<Aes128>;
393 let cipher = Aes128Cfb::new_from_slices(key, &iv)
394 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
395 cipher.encrypt(&mut buffer);
396 }
397 24 => {
398 type Aes192Cfb = cfb_mode::Encryptor<Aes192>;
399 let cipher = Aes192Cfb::new_from_slices(key, &iv)
400 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
401 cipher.encrypt(&mut buffer);
402 }
403 32 => {
404 type Aes256Cfb = cfb_mode::Encryptor<Aes256>;
405 let cipher = Aes256Cfb::new_from_slices(key, &iv)
406 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
407 cipher.encrypt(&mut buffer);
408 }
409 _ => {
410 return Err(Error::encrypt(None, CryptoErrorKind::UnsupportedProtocol));
411 }
412 }
413
414 Ok((Bytes::from(buffer), Bytes::copy_from_slice(&salt_bytes)))
415 }
416
417 fn decrypt_aes(
419 &self,
420 ciphertext: &[u8],
421 engine_boots: u32,
422 engine_time: u32,
423 priv_params: &[u8],
424 ) -> Result<Bytes> {
425 use aes::{Aes128, Aes192, Aes256};
426 use cfb_mode::cipher::{AsyncStreamCipher, KeyIvInit};
427
428 let key_len = match self.protocol {
429 PrivProtocol::Aes128 => 16,
430 PrivProtocol::Aes192 => 24,
431 PrivProtocol::Aes256 => 32,
432 _ => unreachable!(),
433 };
434
435 let key = &self.key[..key_len];
437
438 let mut iv = [0u8; 16];
440 iv[..4].copy_from_slice(&engine_boots.to_be_bytes());
441 iv[4..8].copy_from_slice(&engine_time.to_be_bytes());
442 iv[8..].copy_from_slice(priv_params);
443
444 let mut buffer = ciphertext.to_vec();
445
446 match key_len {
447 16 => {
448 type Aes128Cfb = cfb_mode::Decryptor<Aes128>;
449 let cipher = Aes128Cfb::new_from_slices(key, &iv)
450 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
451 cipher.decrypt(&mut buffer);
452 }
453 24 => {
454 type Aes192Cfb = cfb_mode::Decryptor<Aes192>;
455 let cipher = Aes192Cfb::new_from_slices(key, &iv)
456 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
457 cipher.decrypt(&mut buffer);
458 }
459 32 => {
460 type Aes256Cfb = cfb_mode::Decryptor<Aes256>;
461 let cipher = Aes256Cfb::new_from_slices(key, &iv)
462 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
463 cipher.decrypt(&mut buffer);
464 }
465 _ => {
466 return Err(Error::decrypt(None, CryptoErrorKind::UnsupportedProtocol));
467 }
468 }
469
470 Ok(Bytes::from(buffer))
471 }
472}
473
474impl std::fmt::Debug for PrivKey {
475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
476 f.debug_struct("PrivKey")
477 .field("protocol", &self.protocol)
478 .field("key", &"[REDACTED]")
479 .finish()
480 }
481}
482
483#[cfg(test)]
484mod tests {
485 use super::*;
486 use crate::format::hex::decode as decode_hex;
487
488 #[test]
489 fn test_des_encrypt_decrypt_roundtrip() {
490 let key = vec![
492 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, ];
495 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
496
497 let plaintext = b"Hello, SNMPv3 World!";
498 let engine_boots = 100u32;
499 let engine_time = 12345u32;
500
501 let (ciphertext, priv_params) = priv_key
502 .encrypt(plaintext, engine_boots, engine_time, None)
503 .expect("encryption failed");
504
505 assert_ne!(ciphertext.as_ref(), plaintext);
507 assert_eq!(priv_params.len(), 8);
509
510 let decrypted = priv_key
512 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
513 .expect("decryption failed");
514
515 assert!(decrypted.len() >= plaintext.len());
517 assert_eq!(&decrypted[..plaintext.len()], plaintext);
518 }
519
520 #[test]
521 fn test_aes128_encrypt_decrypt_roundtrip() {
522 let key = vec![
524 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
525 0x0f, 0x10,
526 ];
527 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
528
529 let plaintext = b"Hello, SNMPv3 AES World!";
530 let engine_boots = 200u32;
531 let engine_time = 54321u32;
532
533 let (ciphertext, priv_params) = priv_key
534 .encrypt(plaintext, engine_boots, engine_time, None)
535 .expect("encryption failed");
536
537 assert_ne!(ciphertext.as_ref(), plaintext);
539 assert_eq!(priv_params.len(), 8);
541
542 let decrypted = priv_key
544 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
545 .expect("decryption failed");
546
547 assert_eq!(decrypted.len(), plaintext.len());
549 assert_eq!(decrypted.as_ref(), plaintext);
550 }
551
552 #[test]
553 fn test_des_invalid_ciphertext_length() {
554 let key = vec![0u8; 16];
555 let priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
556
557 let ciphertext = [0u8; 13];
559 let priv_params = [0u8; 8];
560
561 let result = priv_key.decrypt(&ciphertext, 0, 0, &priv_params);
562 assert!(result.is_err());
563 }
564
565 #[test]
566 fn test_invalid_priv_params_length() {
567 let key = vec![0u8; 16];
568 let priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
569
570 let ciphertext = [0u8; 16];
572 let priv_params = [0u8; 4]; let result = priv_key.decrypt(&ciphertext, 0, 0, &priv_params);
575 assert!(result.is_err());
576 }
577
578 #[test]
579 fn test_salt_counter() {
580 let counter = SaltCounter::new();
581 let s1 = counter.next();
582 let s2 = counter.next();
583 let s3 = counter.next();
584
585 assert_eq!(s2, s1.wrapping_add(1));
587 assert_eq!(s3, s2.wrapping_add(1));
588 }
589
590 #[test]
591 fn test_multiple_encryptions_different_salt() {
592 let key = vec![0u8; 16];
593 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
594
595 let plaintext = b"test data";
596
597 let (_, salt1) = priv_key.encrypt(plaintext, 0, 0, None).unwrap();
598 let (_, salt2) = priv_key.encrypt(plaintext, 0, 0, None).unwrap();
599
600 assert_ne!(salt1, salt2);
602 }
603
604 #[test]
605 fn test_from_password() {
606 let password = b"maplesyrup";
608 let engine_id = decode_hex("000000000000000000000002").unwrap();
609
610 let mut priv_key = PrivKey::from_password(
611 AuthProtocol::Sha1,
612 PrivProtocol::Aes128,
613 password,
614 &engine_id,
615 );
616
617 let plaintext = b"test message";
619 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
620 let decrypted = priv_key
621 .decrypt(&ciphertext, 100, 200, &priv_params)
622 .unwrap();
623
624 assert_eq!(decrypted.as_ref(), plaintext);
625 }
626
627 #[test]
628 fn test_aes192_encrypt_decrypt_roundtrip() {
629 let key = vec![
631 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
632 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
633 ];
634 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, key);
635
636 let plaintext = b"Hello, SNMPv3 AES-192 World!";
637 let engine_boots = 300u32;
638 let engine_time = 67890u32;
639
640 let (ciphertext, priv_params) = priv_key
641 .encrypt(plaintext, engine_boots, engine_time, None)
642 .expect("AES-192 encryption failed");
643
644 assert_ne!(ciphertext.as_ref(), plaintext);
646 assert_eq!(priv_params.len(), 8);
648
649 let decrypted = priv_key
651 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
652 .expect("AES-192 decryption failed");
653
654 assert_eq!(decrypted.len(), plaintext.len());
656 assert_eq!(decrypted.as_ref(), plaintext);
657 }
658
659 #[test]
660 fn test_aes256_encrypt_decrypt_roundtrip() {
661 let key = vec![
663 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
664 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
665 0x1d, 0x1e, 0x1f, 0x20,
666 ];
667 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, key);
668
669 let plaintext = b"Hello, SNMPv3 AES-256 World!";
670 let engine_boots = 400u32;
671 let engine_time = 11111u32;
672
673 let (ciphertext, priv_params) = priv_key
674 .encrypt(plaintext, engine_boots, engine_time, None)
675 .expect("AES-256 encryption failed");
676
677 assert_ne!(ciphertext.as_ref(), plaintext);
679 assert_eq!(priv_params.len(), 8);
681
682 let decrypted = priv_key
684 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
685 .expect("AES-256 decryption failed");
686
687 assert_eq!(decrypted.len(), plaintext.len());
689 assert_eq!(decrypted.as_ref(), plaintext);
690 }
691
692 #[test]
693 fn test_aes192_from_password() {
694 let password = b"longpassword123";
696 let engine_id = decode_hex("80001f8880e9b104617361000000").unwrap();
697
698 let mut priv_key = PrivKey::from_password(
699 AuthProtocol::Sha256, PrivProtocol::Aes192,
701 password,
702 &engine_id,
703 );
704
705 let plaintext = b"test message for AES-192";
706 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
707 let decrypted = priv_key
708 .decrypt(&ciphertext, 100, 200, &priv_params)
709 .unwrap();
710
711 assert_eq!(decrypted.as_ref(), plaintext);
712 }
713
714 #[test]
715 fn test_aes256_from_password() {
716 let password = b"anotherlongpassword456";
718 let engine_id = decode_hex("80001f8880e9b104617361000000").unwrap();
719
720 let mut priv_key = PrivKey::from_password(
721 AuthProtocol::Sha256, PrivProtocol::Aes256,
723 password,
724 &engine_id,
725 );
726
727 let plaintext = b"test message for AES-256";
728 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
729 let decrypted = priv_key
730 .decrypt(&ciphertext, 100, 200, &priv_params)
731 .unwrap();
732
733 assert_eq!(decrypted.as_ref(), plaintext);
734 }
735
736 #[test]
746 fn test_des_wrong_key_produces_garbage() {
747 let correct_key = vec![
749 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
750 0x17, 0x18,
751 ];
752 let wrong_key = vec![
754 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2,
755 0xE1, 0xE0,
756 ];
757
758 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Des, correct_key);
759 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Des, wrong_key);
760
761 let plaintext = b"Secret SNMPv3 message data!";
762 let engine_boots = 100u32;
763 let engine_time = 12345u32;
764
765 let (ciphertext, priv_params) = correct_priv_key
767 .encrypt(plaintext, engine_boots, engine_time, None)
768 .expect("encryption failed");
769
770 let wrong_decrypted = wrong_priv_key
772 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
773 .expect("decryption should succeed cryptographically");
774
775 assert_ne!(
777 &wrong_decrypted[..plaintext.len()],
778 plaintext,
779 "wrong key should NOT produce the original plaintext"
780 );
781
782 let correct_decrypted = correct_priv_key
784 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
785 .expect("correct key decryption failed");
786 assert_eq!(
787 &correct_decrypted[..plaintext.len()],
788 plaintext,
789 "correct key should produce the original plaintext"
790 );
791 }
792
793 #[test]
794 fn test_aes128_wrong_key_produces_garbage() {
795 let correct_key = vec![
796 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
797 0x0f, 0x10,
798 ];
799 let wrong_key = vec![
800 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
801 0xF1, 0xF0,
802 ];
803
804 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, correct_key);
805 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, wrong_key);
806
807 let plaintext = b"Secret AES-128 message data!";
808 let engine_boots = 200u32;
809 let engine_time = 54321u32;
810
811 let (ciphertext, priv_params) = correct_priv_key
813 .encrypt(plaintext, engine_boots, engine_time, None)
814 .expect("encryption failed");
815
816 let wrong_decrypted = wrong_priv_key
818 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
819 .expect("decryption should succeed cryptographically");
820
821 assert_ne!(
823 wrong_decrypted.as_ref(),
824 plaintext,
825 "wrong key should NOT produce the original plaintext"
826 );
827
828 let correct_decrypted = correct_priv_key
830 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
831 .expect("correct key decryption failed");
832 assert_eq!(correct_decrypted.as_ref(), plaintext);
833 }
834
835 #[test]
836 fn test_aes192_wrong_key_produces_garbage() {
837 let correct_key = vec![
838 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
839 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
840 ];
841 let wrong_key = vec![
842 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
843 0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
844 ];
845
846 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, correct_key);
847 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, wrong_key);
848
849 let plaintext = b"Secret AES-192 message data!";
850 let engine_boots = 300u32;
851 let engine_time = 67890u32;
852
853 let (ciphertext, priv_params) = correct_priv_key
854 .encrypt(plaintext, engine_boots, engine_time, None)
855 .expect("encryption failed");
856
857 let wrong_decrypted = wrong_priv_key
858 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
859 .expect("decryption should succeed cryptographically");
860
861 assert_ne!(
862 wrong_decrypted.as_ref(),
863 plaintext,
864 "wrong key should NOT produce the original plaintext"
865 );
866 }
867
868 #[test]
869 fn test_aes256_wrong_key_produces_garbage() {
870 let correct_key = vec![
871 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
872 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
873 0x1d, 0x1e, 0x1f, 0x20,
874 ];
875 let wrong_key = vec![
876 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
877 0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7, 0xE6, 0xE5, 0xE4,
878 0xE3, 0xE2, 0xE1, 0xE0,
879 ];
880
881 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, correct_key);
882 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, wrong_key);
883
884 let plaintext = b"Secret AES-256 message data!";
885 let engine_boots = 400u32;
886 let engine_time = 11111u32;
887
888 let (ciphertext, priv_params) = correct_priv_key
889 .encrypt(plaintext, engine_boots, engine_time, None)
890 .expect("encryption failed");
891
892 let wrong_decrypted = wrong_priv_key
893 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
894 .expect("decryption should succeed cryptographically");
895
896 assert_ne!(
897 wrong_decrypted.as_ref(),
898 plaintext,
899 "wrong key should NOT produce the original plaintext"
900 );
901 }
902
903 #[test]
904 fn test_des_wrong_priv_params_produces_garbage() {
905 let key = vec![
908 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
909 0x17, 0x18,
910 ];
911
912 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
913
914 let plaintext = b"DES test message";
915 let engine_boots = 100u32;
916 let engine_time = 12345u32;
917
918 let (ciphertext, correct_priv_params) = priv_key
919 .encrypt(plaintext, engine_boots, engine_time, None)
920 .expect("encryption failed");
921
922 let wrong_priv_params = [0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88];
924
925 let wrong_decrypted = priv_key
926 .decrypt(&ciphertext, engine_boots, engine_time, &wrong_priv_params)
927 .expect("decryption should succeed cryptographically");
928
929 assert_ne!(
931 &wrong_decrypted[..plaintext.len()],
932 plaintext,
933 "wrong priv_params should NOT produce the original plaintext"
934 );
935
936 let correct_decrypted = priv_key
938 .decrypt(&ciphertext, engine_boots, engine_time, &correct_priv_params)
939 .expect("correct decryption failed");
940 assert_eq!(&correct_decrypted[..plaintext.len()], plaintext);
941 }
942
943 #[test]
944 fn test_aes_wrong_engine_time_produces_garbage() {
945 let key = vec![
948 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
949 0x0f, 0x10,
950 ];
951
952 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
953
954 let plaintext = b"AES test message";
955 let engine_boots = 200u32;
956 let engine_time = 54321u32;
957
958 let (ciphertext, priv_params) = priv_key
959 .encrypt(plaintext, engine_boots, engine_time, None)
960 .expect("encryption failed");
961
962 let wrong_decrypted = priv_key
964 .decrypt(&ciphertext, engine_boots, engine_time + 1, &priv_params)
965 .expect("decryption should succeed cryptographically");
966
967 assert_ne!(
968 wrong_decrypted.as_ref(),
969 plaintext,
970 "wrong engine_time should NOT produce the original plaintext"
971 );
972
973 let wrong_decrypted2 = priv_key
975 .decrypt(&ciphertext, engine_boots + 1, engine_time, &priv_params)
976 .expect("decryption should succeed cryptographically");
977
978 assert_ne!(
979 wrong_decrypted2.as_ref(),
980 plaintext,
981 "wrong engine_boots should NOT produce the original plaintext"
982 );
983 }
984}