use chrono::Utc;
use x25519_dalek::{PublicKey, StaticSecret};
use relay_crypto::{crypto::CryptoError, prelude::e2e, record::KeyRecord, rng::os_rng_hkdf};
#[test]
fn encrypt_decrypt_roundtrip() {
let mut recipient_rng = os_rng_hkdf(Some(b"recipient nonce"), b"e2e/test").expect("RNG failed");
let (recipient_secret, recipient_record) = {
let recipient_secret = StaticSecret::random_from_rng(&mut recipient_rng);
let recipient_pub = PublicKey::from(&recipient_secret);
let recipient_pub_bytes = recipient_pub.as_bytes();
(
recipient_secret,
KeyRecord {
id: "test".to_string(),
version: 1,
x25519: *recipient_pub_bytes,
ed25519: [0u8; 32],
created_at: Utc::now(),
expires_at: None,
},
)
};
let rng = os_rng_hkdf(Some(b"encryption nonce"), b"e2e/test").expect("RNG failed");
let message = b"Hello, world!";
let aad = b"canonical-meta-payload";
let (meta, ciphertext) =
e2e::encrypt(rng, &recipient_record, message, aad).expect("Encryption failed");
let payload =
e2e::decrypt(&recipient_secret, &meta, &ciphertext, aad).expect("Decryption failed");
assert_eq!(payload, message);
}
#[test]
fn decrypt_rejects_wrong_add() {
let mut recipient_rng = os_rng_hkdf(Some(b"recipient nonce"), b"e2e/test").expect("RNG failed");
let (recipient_secret, recipient_record) = {
let recipient_secret = StaticSecret::random_from_rng(&mut recipient_rng);
let recipient_pub = PublicKey::from(&recipient_secret);
let recipient_pub_bytes = recipient_pub.as_bytes();
(
recipient_secret,
KeyRecord {
id: "test".to_string(),
version: 1,
x25519: *recipient_pub_bytes,
ed25519: [0u8; 32],
created_at: Utc::now(),
expires_at: None,
},
)
};
let rng = os_rng_hkdf(Some(b"encryption nonce"), b"e2e/test").expect("RNG failed");
let message = b"Hello, world!";
let aad_encrypt = b"canonical-meta-payload";
let aad_decrypt = b"modified-meta-payload";
let (meta, ciphertext) =
e2e::encrypt(rng, &recipient_record, message, aad_encrypt).expect("Encryption failed");
let payload_error = e2e::decrypt(&recipient_secret, &meta, &ciphertext, aad_decrypt)
.expect_err("Decryption should have failed with wrong AAD");
assert_eq!(
payload_error,
CryptoError::Decrypt("aead::Error".to_string())
);
}
#[test]
fn decrypt_rejects_wrong_alg() {
let mut recipient_rng = os_rng_hkdf(Some(b"recipient nonce"), b"e2e/test").expect("RNG failed");
let (recipient_secret, recipient_record) = {
let recipient_secret = StaticSecret::random_from_rng(&mut recipient_rng);
let recipient_pub = PublicKey::from(&recipient_secret);
let recipient_pub_bytes = recipient_pub.as_bytes();
(
recipient_secret,
KeyRecord {
id: "test".to_string(),
version: 1,
x25519: *recipient_pub_bytes,
ed25519: [0u8; 32],
created_at: Utc::now(),
expires_at: None,
},
)
};
let rng = os_rng_hkdf(Some(b"encryption nonce"), b"e2e/test").expect("RNG failed");
let message = b"Hello, world!";
let aad = b"canonical-meta-payload";
let (mut meta, ciphertext) =
e2e::encrypt(rng, &recipient_record, message, aad).expect("Encryption failed");
meta.alg = "wrong-algorithm".to_string();
let payload_error = e2e::decrypt(&recipient_secret, &meta, &ciphertext, aad)
.expect_err("Decryption should have failed with wrong AAD");
assert_eq!(
payload_error,
CryptoError::InvalidMeta("Unsupported algorithm: wrong-algorithm".to_string())
);
}
#[test]
fn decrypt_rejects_corrupt_nonce() {
let mut recipient_rng = os_rng_hkdf(Some(b"recipient nonce"), b"e2e/test").expect("RNG failed");
let (recipient_secret, recipient_record) = {
let recipient_secret = StaticSecret::random_from_rng(&mut recipient_rng);
let recipient_pub = PublicKey::from(&recipient_secret);
let recipient_pub_bytes = recipient_pub.as_bytes();
(
recipient_secret,
KeyRecord {
id: "test".to_string(),
version: 1,
x25519: *recipient_pub_bytes,
ed25519: [0u8; 32],
created_at: Utc::now(),
expires_at: None,
},
)
};
let rng = os_rng_hkdf(Some(b"encryption nonce"), b"e2e/test").expect("RNG failed");
let message = b"Hello, world!";
let aad = b"canonical-meta-payload";
let (mut meta, ciphertext) =
e2e::encrypt(rng, &recipient_record, message, aad).expect("Encryption failed");
meta.nonce = [0u8; 24].to_vec();
let payload_error = e2e::decrypt(&recipient_secret, &meta, &ciphertext, aad)
.expect_err("Decryption should have failed with wrong AAD");
assert_eq!(
payload_error,
CryptoError::Decrypt("aead::Error".to_string())
);
}