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_password_extended(
131 auth_protocol: AuthProtocol,
132 priv_protocol: PrivProtocol,
133 password: &[u8],
134 engine_id: &[u8],
135 key_extension: super::KeyExtension,
136 ) -> Self {
137 use super::{KeyExtension, MasterKey, auth::extend_key};
138
139 let master = MasterKey::from_password(auth_protocol, password);
140 let localized = master.localize(engine_id);
141 let key_bytes = localized.as_bytes();
142
143 let key = match key_extension {
144 KeyExtension::None => key_bytes.to_vec(),
145 KeyExtension::Blumenthal => {
146 extend_key(auth_protocol, key_bytes, priv_protocol.key_len())
147 }
148 };
149
150 Self {
151 key,
152 protocol: priv_protocol,
153 salt_counter: Self::init_salt(),
154 }
155 }
156
157 pub fn from_master_key(
172 master: &super::MasterKey,
173 priv_protocol: PrivProtocol,
174 engine_id: &[u8],
175 ) -> Self {
176 let auth_protocol = master.protocol();
177
178 if !auth_protocol.is_compatible_with(priv_protocol) {
180 tracing::warn!(
181 auth_protocol = ?auth_protocol,
182 priv_protocol = ?priv_protocol,
183 auth_key_len = auth_protocol.digest_len(),
184 required_key_len = priv_protocol.key_len(),
185 "authentication protocol produces insufficient key material for privacy protocol; \
186 use SHA-224+ for AES-192, SHA-256+ for AES-256"
187 );
188 }
189
190 let localized = master.localize(engine_id);
192 let key = localized.as_bytes().to_vec();
193
194 Self {
195 key,
196 protocol: priv_protocol,
197 salt_counter: Self::init_salt(),
198 }
199 }
200
201 pub fn from_bytes(protocol: PrivProtocol, key: impl Into<Vec<u8>>) -> Self {
203 Self {
204 key: key.into(),
205 protocol,
206 salt_counter: Self::init_salt(),
207 }
208 }
209
210 fn init_salt() -> u64 {
212 std::time::SystemTime::now()
213 .duration_since(std::time::UNIX_EPOCH)
214 .map(|d| d.as_nanos() as u64)
215 .unwrap_or(0)
216 }
217
218 pub fn protocol(&self) -> PrivProtocol {
220 self.protocol
221 }
222
223 pub fn encryption_key(&self) -> &[u8] {
225 match self.protocol {
226 PrivProtocol::Des => &self.key[..8],
227 PrivProtocol::Aes128 => &self.key[..16],
228 PrivProtocol::Aes192 => &self.key[..24],
229 PrivProtocol::Aes256 => &self.key[..32],
230 }
231 }
232
233 pub fn encrypt(
245 &mut self,
246 plaintext: &[u8],
247 engine_boots: u32,
248 engine_time: u32,
249 salt_counter: Option<&SaltCounter>,
250 ) -> Result<(Bytes, Bytes)> {
251 let salt = salt_counter.map(|c| c.next()).unwrap_or_else(|| {
252 let s = self.salt_counter;
253 self.salt_counter = self.salt_counter.wrapping_add(1);
254 s
255 });
256
257 match self.protocol {
258 PrivProtocol::Des => self.encrypt_des(plaintext, engine_boots, salt),
259 PrivProtocol::Aes128 => {
260 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 16)
261 }
262 PrivProtocol::Aes192 => {
263 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 24)
264 }
265 PrivProtocol::Aes256 => {
266 self.encrypt_aes(plaintext, engine_boots, engine_time, salt, 32)
267 }
268 }
269 }
270
271 pub fn decrypt(
283 &self,
284 ciphertext: &[u8],
285 engine_boots: u32,
286 engine_time: u32,
287 priv_params: &[u8],
288 ) -> Result<Bytes> {
289 if priv_params.len() != 8 {
290 return Err(Error::decrypt(
291 None,
292 CryptoErrorKind::InvalidPrivParamsLength {
293 expected: 8,
294 actual: priv_params.len(),
295 },
296 ));
297 }
298
299 match self.protocol {
300 PrivProtocol::Des => self.decrypt_des(ciphertext, priv_params),
301 PrivProtocol::Aes128 | PrivProtocol::Aes192 | PrivProtocol::Aes256 => {
302 self.decrypt_aes(ciphertext, engine_boots, engine_time, priv_params)
303 }
304 }
305 }
306
307 fn encrypt_des(
309 &self,
310 plaintext: &[u8],
311 engine_boots: u32,
312 salt_int: u64,
313 ) -> Result<(Bytes, Bytes)> {
314 use cbc::cipher::{BlockEncryptMut, KeyIvInit};
315 type DesCbc = cbc::Encryptor<des::Des>;
316
317 let key = &self.key[..8];
319 let pre_iv = &self.key[8..16];
321
322 let mut salt = [0u8; 8];
325 salt[..4].copy_from_slice(&engine_boots.to_be_bytes());
326 salt[4..].copy_from_slice(&(salt_int as u32).to_be_bytes());
327
328 let mut iv = [0u8; 8];
330 for i in 0..8 {
331 iv[i] = pre_iv[i] ^ salt[i];
332 }
333
334 let pad_len = (8 - (plaintext.len() % 8)) % 8;
336 let padded_len = plaintext.len() + if pad_len == 0 { 0 } else { pad_len };
337 let padded_len = if padded_len == plaintext.len() && !plaintext.len().is_multiple_of(8) {
339 plaintext.len() + (8 - plaintext.len() % 8)
340 } else {
341 padded_len
342 };
343
344 let mut buffer = vec![
345 0u8;
346 if padded_len > plaintext.len() {
347 padded_len
348 } else {
349 plaintext.len() + 8 - (plaintext.len() % 8)
350 }
351 ];
352 let padded_len = buffer.len();
353 buffer[..plaintext.len()].copy_from_slice(plaintext);
354
355 let cipher = DesCbc::new_from_slices(key, &iv)
357 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
358
359 let ciphertext = cipher
360 .encrypt_padded_mut::<cbc::cipher::block_padding::NoPadding>(&mut buffer, padded_len)
361 .map_err(|_| Error::encrypt(None, CryptoErrorKind::CipherError))?;
362
363 Ok((
364 Bytes::copy_from_slice(ciphertext),
365 Bytes::copy_from_slice(&salt),
366 ))
367 }
368
369 fn decrypt_des(&self, ciphertext: &[u8], priv_params: &[u8]) -> Result<Bytes> {
371 use cbc::cipher::{BlockDecryptMut, KeyIvInit};
372 type DesCbc = cbc::Decryptor<des::Des>;
373
374 if !ciphertext.len().is_multiple_of(8) {
375 return Err(Error::decrypt(
376 None,
377 CryptoErrorKind::InvalidCiphertextLength {
378 length: ciphertext.len(),
379 block_size: 8,
380 },
381 ));
382 }
383
384 let key = &self.key[..8];
386 let pre_iv = &self.key[8..16];
388
389 let salt = priv_params;
391
392 let mut iv = [0u8; 8];
394 for i in 0..8 {
395 iv[i] = pre_iv[i] ^ salt[i];
396 }
397
398 let cipher = DesCbc::new_from_slices(key, &iv)
400 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
401
402 let mut buffer = ciphertext.to_vec();
403 let plaintext = cipher
404 .decrypt_padded_mut::<cbc::cipher::block_padding::NoPadding>(&mut buffer)
405 .map_err(|_| Error::decrypt(None, CryptoErrorKind::CipherError))?;
406
407 Ok(Bytes::copy_from_slice(plaintext))
408 }
409
410 fn encrypt_aes(
412 &self,
413 plaintext: &[u8],
414 engine_boots: u32,
415 engine_time: u32,
416 salt: u64,
417 key_len: usize,
418 ) -> Result<(Bytes, Bytes)> {
419 use aes::{Aes128, Aes192, Aes256};
420 use cfb_mode::cipher::{AsyncStreamCipher, KeyIvInit};
421
422 let key = &self.key[..key_len];
424
425 let salt_bytes = salt.to_be_bytes();
427
428 let mut iv = [0u8; 16];
431 iv[..4].copy_from_slice(&engine_boots.to_be_bytes());
432 iv[4..8].copy_from_slice(&engine_time.to_be_bytes());
433 iv[8..].copy_from_slice(&salt_bytes);
434
435 let mut buffer = plaintext.to_vec();
436
437 match key_len {
438 16 => {
439 type Aes128Cfb = cfb_mode::Encryptor<Aes128>;
440 let cipher = Aes128Cfb::new_from_slices(key, &iv)
441 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
442 cipher.encrypt(&mut buffer);
443 }
444 24 => {
445 type Aes192Cfb = cfb_mode::Encryptor<Aes192>;
446 let cipher = Aes192Cfb::new_from_slices(key, &iv)
447 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
448 cipher.encrypt(&mut buffer);
449 }
450 32 => {
451 type Aes256Cfb = cfb_mode::Encryptor<Aes256>;
452 let cipher = Aes256Cfb::new_from_slices(key, &iv)
453 .map_err(|_| Error::encrypt(None, CryptoErrorKind::InvalidKeyLength))?;
454 cipher.encrypt(&mut buffer);
455 }
456 _ => {
457 return Err(Error::encrypt(None, CryptoErrorKind::UnsupportedProtocol));
458 }
459 }
460
461 Ok((Bytes::from(buffer), Bytes::copy_from_slice(&salt_bytes)))
462 }
463
464 fn decrypt_aes(
466 &self,
467 ciphertext: &[u8],
468 engine_boots: u32,
469 engine_time: u32,
470 priv_params: &[u8],
471 ) -> Result<Bytes> {
472 use aes::{Aes128, Aes192, Aes256};
473 use cfb_mode::cipher::{AsyncStreamCipher, KeyIvInit};
474
475 let key_len = match self.protocol {
476 PrivProtocol::Aes128 => 16,
477 PrivProtocol::Aes192 => 24,
478 PrivProtocol::Aes256 => 32,
479 _ => unreachable!(),
480 };
481
482 let key = &self.key[..key_len];
484
485 let mut iv = [0u8; 16];
487 iv[..4].copy_from_slice(&engine_boots.to_be_bytes());
488 iv[4..8].copy_from_slice(&engine_time.to_be_bytes());
489 iv[8..].copy_from_slice(priv_params);
490
491 let mut buffer = ciphertext.to_vec();
492
493 match key_len {
494 16 => {
495 type Aes128Cfb = cfb_mode::Decryptor<Aes128>;
496 let cipher = Aes128Cfb::new_from_slices(key, &iv)
497 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
498 cipher.decrypt(&mut buffer);
499 }
500 24 => {
501 type Aes192Cfb = cfb_mode::Decryptor<Aes192>;
502 let cipher = Aes192Cfb::new_from_slices(key, &iv)
503 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
504 cipher.decrypt(&mut buffer);
505 }
506 32 => {
507 type Aes256Cfb = cfb_mode::Decryptor<Aes256>;
508 let cipher = Aes256Cfb::new_from_slices(key, &iv)
509 .map_err(|_| Error::decrypt(None, CryptoErrorKind::InvalidKeyLength))?;
510 cipher.decrypt(&mut buffer);
511 }
512 _ => {
513 return Err(Error::decrypt(None, CryptoErrorKind::UnsupportedProtocol));
514 }
515 }
516
517 Ok(Bytes::from(buffer))
518 }
519}
520
521impl std::fmt::Debug for PrivKey {
522 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
523 f.debug_struct("PrivKey")
524 .field("protocol", &self.protocol)
525 .field("key", &"[REDACTED]")
526 .finish()
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use super::*;
533 use crate::format::hex::decode as decode_hex;
534
535 #[test]
536 fn test_des_encrypt_decrypt_roundtrip() {
537 let key = vec![
539 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, ];
542 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
543
544 let plaintext = b"Hello, SNMPv3 World!";
545 let engine_boots = 100u32;
546 let engine_time = 12345u32;
547
548 let (ciphertext, priv_params) = priv_key
549 .encrypt(plaintext, engine_boots, engine_time, None)
550 .expect("encryption failed");
551
552 assert_ne!(ciphertext.as_ref(), plaintext);
554 assert_eq!(priv_params.len(), 8);
556
557 let decrypted = priv_key
559 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
560 .expect("decryption failed");
561
562 assert!(decrypted.len() >= plaintext.len());
564 assert_eq!(&decrypted[..plaintext.len()], plaintext);
565 }
566
567 #[test]
568 fn test_aes128_encrypt_decrypt_roundtrip() {
569 let key = vec![
571 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
572 0x0f, 0x10,
573 ];
574 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
575
576 let plaintext = b"Hello, SNMPv3 AES World!";
577 let engine_boots = 200u32;
578 let engine_time = 54321u32;
579
580 let (ciphertext, priv_params) = priv_key
581 .encrypt(plaintext, engine_boots, engine_time, None)
582 .expect("encryption failed");
583
584 assert_ne!(ciphertext.as_ref(), plaintext);
586 assert_eq!(priv_params.len(), 8);
588
589 let decrypted = priv_key
591 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
592 .expect("decryption failed");
593
594 assert_eq!(decrypted.len(), plaintext.len());
596 assert_eq!(decrypted.as_ref(), plaintext);
597 }
598
599 #[test]
600 fn test_des_invalid_ciphertext_length() {
601 let key = vec![0u8; 16];
602 let priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
603
604 let ciphertext = [0u8; 13];
606 let priv_params = [0u8; 8];
607
608 let result = priv_key.decrypt(&ciphertext, 0, 0, &priv_params);
609 assert!(result.is_err());
610 }
611
612 #[test]
613 fn test_invalid_priv_params_length() {
614 let key = vec![0u8; 16];
615 let priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
616
617 let ciphertext = [0u8; 16];
619 let priv_params = [0u8; 4]; let result = priv_key.decrypt(&ciphertext, 0, 0, &priv_params);
622 assert!(result.is_err());
623 }
624
625 #[test]
626 fn test_salt_counter() {
627 let counter = SaltCounter::new();
628 let s1 = counter.next();
629 let s2 = counter.next();
630 let s3 = counter.next();
631
632 assert_eq!(s2, s1.wrapping_add(1));
634 assert_eq!(s3, s2.wrapping_add(1));
635 }
636
637 #[test]
638 fn test_multiple_encryptions_different_salt() {
639 let key = vec![0u8; 16];
640 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
641
642 let plaintext = b"test data";
643
644 let (_, salt1) = priv_key.encrypt(plaintext, 0, 0, None).unwrap();
645 let (_, salt2) = priv_key.encrypt(plaintext, 0, 0, None).unwrap();
646
647 assert_ne!(salt1, salt2);
649 }
650
651 #[test]
652 fn test_from_password() {
653 let password = b"maplesyrup";
655 let engine_id = decode_hex("000000000000000000000002").unwrap();
656
657 let mut priv_key = PrivKey::from_password(
658 AuthProtocol::Sha1,
659 PrivProtocol::Aes128,
660 password,
661 &engine_id,
662 );
663
664 let plaintext = b"test message";
666 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
667 let decrypted = priv_key
668 .decrypt(&ciphertext, 100, 200, &priv_params)
669 .unwrap();
670
671 assert_eq!(decrypted.as_ref(), plaintext);
672 }
673
674 #[test]
675 fn test_aes192_encrypt_decrypt_roundtrip() {
676 let key = vec![
678 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
679 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
680 ];
681 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, key);
682
683 let plaintext = b"Hello, SNMPv3 AES-192 World!";
684 let engine_boots = 300u32;
685 let engine_time = 67890u32;
686
687 let (ciphertext, priv_params) = priv_key
688 .encrypt(plaintext, engine_boots, engine_time, None)
689 .expect("AES-192 encryption failed");
690
691 assert_ne!(ciphertext.as_ref(), plaintext);
693 assert_eq!(priv_params.len(), 8);
695
696 let decrypted = priv_key
698 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
699 .expect("AES-192 decryption failed");
700
701 assert_eq!(decrypted.len(), plaintext.len());
703 assert_eq!(decrypted.as_ref(), plaintext);
704 }
705
706 #[test]
707 fn test_aes256_encrypt_decrypt_roundtrip() {
708 let key = vec![
710 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
711 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
712 0x1d, 0x1e, 0x1f, 0x20,
713 ];
714 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, key);
715
716 let plaintext = b"Hello, SNMPv3 AES-256 World!";
717 let engine_boots = 400u32;
718 let engine_time = 11111u32;
719
720 let (ciphertext, priv_params) = priv_key
721 .encrypt(plaintext, engine_boots, engine_time, None)
722 .expect("AES-256 encryption failed");
723
724 assert_ne!(ciphertext.as_ref(), plaintext);
726 assert_eq!(priv_params.len(), 8);
728
729 let decrypted = priv_key
731 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
732 .expect("AES-256 decryption failed");
733
734 assert_eq!(decrypted.len(), plaintext.len());
736 assert_eq!(decrypted.as_ref(), plaintext);
737 }
738
739 #[test]
740 fn test_aes192_from_password() {
741 let password = b"longpassword123";
743 let engine_id = decode_hex("80001f8880e9b104617361000000").unwrap();
744
745 let mut priv_key = PrivKey::from_password(
746 AuthProtocol::Sha256, PrivProtocol::Aes192,
748 password,
749 &engine_id,
750 );
751
752 let plaintext = b"test message for AES-192";
753 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
754 let decrypted = priv_key
755 .decrypt(&ciphertext, 100, 200, &priv_params)
756 .unwrap();
757
758 assert_eq!(decrypted.as_ref(), plaintext);
759 }
760
761 #[test]
762 fn test_aes256_from_password() {
763 let password = b"anotherlongpassword456";
765 let engine_id = decode_hex("80001f8880e9b104617361000000").unwrap();
766
767 let mut priv_key = PrivKey::from_password(
768 AuthProtocol::Sha256, PrivProtocol::Aes256,
770 password,
771 &engine_id,
772 );
773
774 let plaintext = b"test message for AES-256";
775 let (ciphertext, priv_params) = priv_key.encrypt(plaintext, 100, 200, None).unwrap();
776 let decrypted = priv_key
777 .decrypt(&ciphertext, 100, 200, &priv_params)
778 .unwrap();
779
780 assert_eq!(decrypted.as_ref(), plaintext);
781 }
782
783 #[test]
793 fn test_des_wrong_key_produces_garbage() {
794 let correct_key = vec![
796 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
797 0x17, 0x18,
798 ];
799 let wrong_key = vec![
801 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2,
802 0xE1, 0xE0,
803 ];
804
805 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Des, correct_key);
806 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Des, wrong_key);
807
808 let plaintext = b"Secret SNMPv3 message data!";
809 let engine_boots = 100u32;
810 let engine_time = 12345u32;
811
812 let (ciphertext, priv_params) = correct_priv_key
814 .encrypt(plaintext, engine_boots, engine_time, None)
815 .expect("encryption failed");
816
817 let wrong_decrypted = wrong_priv_key
819 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
820 .expect("decryption should succeed cryptographically");
821
822 assert_ne!(
824 &wrong_decrypted[..plaintext.len()],
825 plaintext,
826 "wrong key should NOT produce the original plaintext"
827 );
828
829 let correct_decrypted = correct_priv_key
831 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
832 .expect("correct key decryption failed");
833 assert_eq!(
834 &correct_decrypted[..plaintext.len()],
835 plaintext,
836 "correct key should produce the original plaintext"
837 );
838 }
839
840 #[test]
841 fn test_aes128_wrong_key_produces_garbage() {
842 let correct_key = vec![
843 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
844 0x0f, 0x10,
845 ];
846 let wrong_key = vec![
847 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
848 0xF1, 0xF0,
849 ];
850
851 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, correct_key);
852 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, wrong_key);
853
854 let plaintext = b"Secret AES-128 message data!";
855 let engine_boots = 200u32;
856 let engine_time = 54321u32;
857
858 let (ciphertext, priv_params) = correct_priv_key
860 .encrypt(plaintext, engine_boots, engine_time, None)
861 .expect("encryption failed");
862
863 let wrong_decrypted = wrong_priv_key
865 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
866 .expect("decryption should succeed cryptographically");
867
868 assert_ne!(
870 wrong_decrypted.as_ref(),
871 plaintext,
872 "wrong key should NOT produce the original plaintext"
873 );
874
875 let correct_decrypted = correct_priv_key
877 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
878 .expect("correct key decryption failed");
879 assert_eq!(correct_decrypted.as_ref(), plaintext);
880 }
881
882 #[test]
883 fn test_aes192_wrong_key_produces_garbage() {
884 let correct_key = vec![
885 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
886 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
887 ];
888 let wrong_key = vec![
889 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
890 0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
891 ];
892
893 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, correct_key);
894 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes192, wrong_key);
895
896 let plaintext = b"Secret AES-192 message data!";
897 let engine_boots = 300u32;
898 let engine_time = 67890u32;
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_aes256_wrong_key_produces_garbage() {
917 let correct_key = vec![
918 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
919 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
920 0x1d, 0x1e, 0x1f, 0x20,
921 ];
922 let wrong_key = vec![
923 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
924 0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8, 0xE7, 0xE6, 0xE5, 0xE4,
925 0xE3, 0xE2, 0xE1, 0xE0,
926 ];
927
928 let mut correct_priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, correct_key);
929 let wrong_priv_key = PrivKey::from_bytes(PrivProtocol::Aes256, wrong_key);
930
931 let plaintext = b"Secret AES-256 message data!";
932 let engine_boots = 400u32;
933 let engine_time = 11111u32;
934
935 let (ciphertext, priv_params) = correct_priv_key
936 .encrypt(plaintext, engine_boots, engine_time, None)
937 .expect("encryption failed");
938
939 let wrong_decrypted = wrong_priv_key
940 .decrypt(&ciphertext, engine_boots, engine_time, &priv_params)
941 .expect("decryption should succeed cryptographically");
942
943 assert_ne!(
944 wrong_decrypted.as_ref(),
945 plaintext,
946 "wrong key should NOT produce the original plaintext"
947 );
948 }
949
950 #[test]
951 fn test_des_wrong_priv_params_produces_garbage() {
952 let key = vec![
955 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
956 0x17, 0x18,
957 ];
958
959 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Des, key);
960
961 let plaintext = b"DES test message";
962 let engine_boots = 100u32;
963 let engine_time = 12345u32;
964
965 let (ciphertext, correct_priv_params) = priv_key
966 .encrypt(plaintext, engine_boots, engine_time, None)
967 .expect("encryption failed");
968
969 let wrong_priv_params = [0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88];
971
972 let wrong_decrypted = priv_key
973 .decrypt(&ciphertext, engine_boots, engine_time, &wrong_priv_params)
974 .expect("decryption should succeed cryptographically");
975
976 assert_ne!(
978 &wrong_decrypted[..plaintext.len()],
979 plaintext,
980 "wrong priv_params should NOT produce the original plaintext"
981 );
982
983 let correct_decrypted = priv_key
985 .decrypt(&ciphertext, engine_boots, engine_time, &correct_priv_params)
986 .expect("correct decryption failed");
987 assert_eq!(&correct_decrypted[..plaintext.len()], plaintext);
988 }
989
990 #[test]
991 fn test_aes_wrong_engine_time_produces_garbage() {
992 let key = vec![
995 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
996 0x0f, 0x10,
997 ];
998
999 let mut priv_key = PrivKey::from_bytes(PrivProtocol::Aes128, key);
1000
1001 let plaintext = b"AES test message";
1002 let engine_boots = 200u32;
1003 let engine_time = 54321u32;
1004
1005 let (ciphertext, priv_params) = priv_key
1006 .encrypt(plaintext, engine_boots, engine_time, None)
1007 .expect("encryption failed");
1008
1009 let wrong_decrypted = priv_key
1011 .decrypt(&ciphertext, engine_boots, engine_time + 1, &priv_params)
1012 .expect("decryption should succeed cryptographically");
1013
1014 assert_ne!(
1015 wrong_decrypted.as_ref(),
1016 plaintext,
1017 "wrong engine_time should NOT produce the original plaintext"
1018 );
1019
1020 let wrong_decrypted2 = priv_key
1022 .decrypt(&ciphertext, engine_boots + 1, engine_time, &priv_params)
1023 .expect("decryption should succeed cryptographically");
1024
1025 assert_ne!(
1026 wrong_decrypted2.as_ref(),
1027 plaintext,
1028 "wrong engine_boots should NOT produce the original plaintext"
1029 );
1030 }
1031}