//! `crypto_box` test vectors //! //! Adapted from PHP Sodium Compat's test vectors: //! #![cfg(all( any(feature = "chacha20", feature = "salsa20"), feature = "getrandom", feature = "std" ))] use crypto_box::{ aead::{generic_array::GenericArray, Aead, AeadInPlace, OsRng}, PublicKey, SecretKey, }; use curve25519_dalek::EdwardsPoint; use hex_literal::hex; // Alice's keypair const ALICE_SECRET_KEY: [u8; 32] = hex!("68f208412d8dd5db9d0c6d18512e86f0ec75665ab841372d57b042b27ef89d4c"); const ALICE_PUBLIC_KEY: [u8; 32] = hex!("ac3a70ba35df3c3fae427a7c72021d68f2c1e044040b75f17313c0c8b5d4241d"); // Bob's keypair const BOB_SECRET_KEY: [u8; 32] = hex!("b581fb5ae182a16f603f39270d4e3b95bc008310b727a11dd4e784a0044d461b"); const BOB_PUBLIC_KEY: [u8; 32] = hex!("e8980c86e032f1eb2975052e8d65bddd15c3b59641174ec9678a53789d92c754"); const NONCE: &[u8; 24] = &hex!("69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37"); const PLAINTEXT: &[u8] = &[ 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b, 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a, 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31, 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a, 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52, 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40, 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05, ]; #[test] fn generate_secret_key() { SecretKey::generate(&mut OsRng); } #[test] fn secret_and_public_keys() { let secret_key = SecretKey::from(ALICE_SECRET_KEY); assert_eq!(secret_key.to_bytes(), ALICE_SECRET_KEY); // Ensure `Debug` impl on `SecretKey` is covered in tests dbg!(&secret_key); assert_eq!(secret_key.public_key().as_bytes(), &ALICE_PUBLIC_KEY); } #[test] fn edwards_to_montgomery() { let secret_key = SecretKey::from(ALICE_SECRET_KEY); let scalar = secret_key.to_scalar(); let point = EdwardsPoint::mul_base(&scalar); let public_key = PublicKey::from(point.to_montgomery()); assert_eq!(secret_key.public_key(), public_key); assert_eq!(secret_key, SecretKey::from(scalar)); } macro_rules! impl_tests { ($box:ty, $plaintext:expr, $ciphertext:expr) => { #[test] fn encrypt() { let secret_key = SecretKey::from(ALICE_SECRET_KEY); let public_key = PublicKey::from(BOB_PUBLIC_KEY); let nonce = GenericArray::from_slice(NONCE); let ciphertext = <$box>::new(&public_key, &secret_key) .encrypt(nonce, $plaintext) .unwrap(); assert_eq!($ciphertext, &ciphertext[..]); } #[test] fn encrypt_in_place_detached() { let secret_key = SecretKey::from(ALICE_SECRET_KEY); let public_key = PublicKey::from(BOB_PUBLIC_KEY); let nonce = GenericArray::from_slice(NONCE); let mut buffer = $plaintext.to_vec(); let tag = <$box>::new(&public_key, &secret_key) .encrypt_in_place_detached(nonce, b"", &mut buffer) .unwrap(); let (expected_tag, expected_ciphertext) = $ciphertext.split_at(16); assert_eq!(expected_tag, &tag[..]); assert_eq!(expected_ciphertext, &buffer[..]); } #[test] fn decrypt() { let secret_key = SecretKey::from(BOB_SECRET_KEY); let public_key = PublicKey::from(ALICE_PUBLIC_KEY); let nonce = GenericArray::from_slice(NONCE); let plaintext = <$box>::new(&public_key, &secret_key) .decrypt(nonce, $ciphertext) .unwrap(); assert_eq!($plaintext, &plaintext[..]); } #[test] fn decrypt_in_place_detached() { let secret_key = SecretKey::from(BOB_SECRET_KEY); let public_key = PublicKey::from(ALICE_PUBLIC_KEY); let nonce = GenericArray::from_slice(NONCE); let tag = GenericArray::clone_from_slice(&$ciphertext[..16]); let mut buffer = $ciphertext[16..].to_vec(); <$box>::new(&public_key, &secret_key) .decrypt_in_place_detached(nonce, b"", &mut buffer, &tag) .unwrap(); assert_eq!($plaintext, &buffer[..]); } }; } #[cfg(feature = "salsa20")] mod xsalsa20poly1305 { use super::*; use crypto_box::SalsaBox; const CIPHERTEXT: &[u8] = &[ 0xc0, 0x3f, 0x27, 0xd1, 0x88, 0xef, 0x65, 0xc, 0xd1, 0x29, 0x36, 0x91, 0x31, 0x37, 0xbb, 0x17, 0xed, 0x4c, 0x98, 0xc2, 0x64, 0x89, 0x39, 0xe2, 0xe1, 0xd2, 0xe8, 0x55, 0x47, 0xa, 0x7b, 0x8c, 0x63, 0x2c, 0xab, 0xfd, 0x5a, 0xb3, 0xb3, 0xc2, 0xd3, 0x13, 0xdc, 0x8c, 0x9e, 0xcf, 0x5d, 0xa1, 0x73, 0xe1, 0xf9, 0xc3, 0x18, 0xcd, 0xef, 0x1d, 0xce, 0xd6, 0xd2, 0x51, 0x9e, 0x69, 0x50, 0x85, 0xe6, 0xb5, 0xc4, 0x1, 0xa2, 0xbd, 0x53, 0x31, 0x44, 0x29, 0x86, 0xc7, 0x7, 0x6d, 0x41, 0x26, 0x25, 0x49, 0x7c, 0x4c, 0xb2, 0xfd, 0x94, 0xc6, 0xf1, 0x3, 0x96, 0x10, 0x33, 0xb2, 0xc9, 0x30, 0xd7, 0xe8, 0x2e, 0x3, 0x41, 0xf2, 0x9d, 0x38, 0x79, 0xbd, 0x6a, 0xb9, 0xd8, 0x81, 0xea, 0x3a, 0x1f, 0x36, 0x5d, 0x63, 0x4e, 0x65, 0x3c, 0x6e, 0x17, 0x1a, 0xac, 0x7f, 0xc1, 0xe7, 0x69, 0x34, 0xd2, 0x3b, 0xe6, 0xf0, 0x4a, 0x54, 0x1, 0x8, 0x8, 0xdb, 0xf0, 0xf9, 0xbd, 0x30, 0xf6, 0x3b, 0x68, 0xd0, 0x26, ]; impl_tests!(SalsaBox, PLAINTEXT, CIPHERTEXT); } #[cfg(feature = "chacha20")] mod xchacha20poly1305 { use super::*; use crypto_box::ChaChaBox; const CIPHERTEXT: &[u8] = &hex!( "0cd5ed093de698c8e410d0d451df2f5283057376b947b9b7392b956e5d675f309218acce8cf85f6c" "f6a9e2e09ef8c5b0f97c661ee21b1b3418be566692634056a92b4034d5d0cf14c52420a488b7f0da" "0c5740dfc6b85397d3a8f679e84303e8d3f8b048abdb2dd79183b0a62683a1bc2a527fc9b82c5ffa" "c4a684bcfeadfdcd28930b2dbe597f4716a658ccfca5b44049e06c" ); impl_tests!(ChaChaBox, PLAINTEXT, CIPHERTEXT); } #[cfg(feature = "seal")] #[test] fn seal() { const SEAL_SECRET_KEY: [u8; 32] = [ 0x15, 0xb3, 0x6c, 0xb0, 0x02, 0x13, 0x37, 0x3f, 0xb3, 0xfb, 0x03, 0x95, 0x8f, 0xb0, 0xcc, 0x00, 0x12, 0xec, 0xac, 0xa1, 0x12, 0xfd, 0x24, 0x9d, 0x3c, 0xf0, 0x96, 0x1e, 0x31, 0x1c, 0xaa, 0xc9, ]; const SEAL_PUBLIC_KEY: [u8; 32] = [ 0xfb, 0x4c, 0xb3, 0x4f, 0x74, 0xa9, 0x28, 0xb7, 0x91, 0x23, 0x33, 0x3c, 0x1e, 0x63, 0xd9, 0x91, 0x06, 0x02, 0x44, 0xcd, 0xa9, 0x8a, 0xff, 0xee, 0x14, 0xc3, 0x39, 0x8c, 0x6d, 0x31, 0x55, 0x74, ]; const SEAL_PLAINTEXT: &[u8] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.".as_bytes(); const SEAL_CIPHERTEXT: &[u8] = &[ 0x95, 0xeb, 0x5b, 0xf0, 0x5a, 0xda, 0x25, 0xee, 0x51, 0xf4, 0x15, 0x82, 0x01, 0xc2, 0x61, 0xa0, 0x0b, 0xfb, 0x19, 0x55, 0xa9, 0x17, 0x6c, 0x8c, 0x7f, 0x1a, 0x62, 0xf2, 0x99, 0xa3, 0x2e, 0x54, 0xf6, 0xeb, 0xcc, 0xc8, 0xab, 0x9d, 0x2c, 0xe1, 0xb1, 0xd3, 0x71, 0x0b, 0xa3, 0x7d, 0x8d, 0xb1, 0x7a, 0xee, 0xec, 0x0b, 0x78, 0xfc, 0x3d, 0x32, 0xb3, 0x9b, 0x79, 0xed, 0x96, 0xf1, 0x89, 0x48, 0xc5, 0xa5, 0x74, 0xb8, 0xe3, 0xf8, 0xec, 0xcc, 0x2f, 0x13, 0x24, 0x08, 0xc2, 0x16, 0x46, 0xf3, 0xae, 0xda, 0xe4, 0xa6, 0x7f, 0xde, 0x4f, 0x77, 0x15, 0x3b, 0x54, 0x58, 0xb8, 0xa6, 0xbd, 0x71, 0x2d, 0xd8, 0x36, 0x55, 0x34, 0xc5, 0x67, 0xec, ]; let pk = PublicKey::from(SEAL_PUBLIC_KEY); let encrypted = pk.seal(&mut OsRng, SEAL_PLAINTEXT).unwrap(); let sk = SecretKey::from(SEAL_SECRET_KEY); assert_eq!(SEAL_PLAINTEXT, sk.unseal(&encrypted).unwrap()); assert_eq!(SEAL_PLAINTEXT, sk.unseal(SEAL_CIPHERTEXT).unwrap()); }