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