#![cfg(feature = "encrypt")]
use bc_components::SymmetricKey;
use bc_envelope::prelude::*;
use indoc::indoc;
mod common;
use crate::common::{check_encoding::*, test_data::*};
#[test]
fn plaintext() {
bc_components::register_tags();
let envelope = hello_envelope();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
"Hello."
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_plaintext = Envelope::from_ur(&ur)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(received_plaintext, PLAINTEXT_HELLO);
}
#[test]
fn symmetric_encryption() {
bc_components::register_tags();
let key = SymmetricKey::new();
let envelope = hello_envelope()
.encrypt_subject(&key)
.unwrap()
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope =
Envelope::from_ur(&ur).unwrap().check_encoding().unwrap();
let received_plaintext = received_envelope
.decrypt_subject(&key)
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(received_plaintext, PLAINTEXT_HELLO);
assert!(received_envelope.extract_subject::<String>().is_err());
assert!(
received_envelope
.decrypt_subject(&SymmetricKey::new())
.is_err()
);
}
fn round_trip_test(envelope: Envelope) {
let key = SymmetricKey::new();
let plaintext_subject = envelope.check_encoding().unwrap();
let encrypted_subject = plaintext_subject.encrypt_subject(&key).unwrap();
assert!(encrypted_subject.is_equivalent_to(&plaintext_subject));
let plaintext_subject2 = encrypted_subject
.decrypt_subject(&key)
.unwrap()
.check_encoding()
.unwrap();
assert!(encrypted_subject.is_equivalent_to(&plaintext_subject2));
assert!(plaintext_subject.is_identical_to(&plaintext_subject2));
}
#[test]
fn encrypt_decrypt() {
let e = Envelope::new(PLAINTEXT_HELLO);
round_trip_test(e);
let e = Envelope::new("Alice").add_assertion("knows", "Bob");
round_trip_test(e);
let e = Envelope::new("Alice").wrap();
round_trip_test(e);
let e = Envelope::new(known_values::IS_A);
round_trip_test(e);
let e = Envelope::new_assertion("knows", "Bob");
round_trip_test(e);
#[cfg(feature = "compress")]
{
let e = Envelope::new(PLAINTEXT_HELLO).compress().unwrap();
round_trip_test(e);
}
}
#[cfg(all(feature = "signature", feature = "secp256k1"))]
#[test]
fn sign_then_encrypt() {
bc_components::register_tags();
let key = SymmetricKey::new();
let envelope = hello_envelope()
.add_signature(&alice_private_key())
.check_encoding()
.unwrap()
.wrap()
.check_encoding()
.unwrap()
.encrypt_subject(&key)
.unwrap()
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_plaintext = Envelope::from_ur(&ur)
.unwrap()
.check_encoding()
.unwrap()
.decrypt_subject(&key)
.unwrap()
.check_encoding()
.unwrap()
.try_unwrap()
.unwrap()
.check_encoding()
.unwrap()
.verify_signature_from(&alice_public_key());
let received_plaintext = received_plaintext
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(received_plaintext, PLAINTEXT_HELLO);
}
#[cfg(all(feature = "signature", feature = "secp256k1"))]
#[test]
fn test_encrypt_then_sign() {
bc_components::register_tags();
let key = SymmetricKey::new();
let envelope = hello_envelope()
.encrypt_subject(&key)
.unwrap()
.add_signature(&alice_private_key())
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'signed': Signature
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_plaintext = Envelope::from_ur(&ur)
.unwrap()
.check_encoding()
.unwrap()
.verify_signature_from(&alice_public_key())
.unwrap()
.decrypt_subject(&key)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(received_plaintext, PLAINTEXT_HELLO);
}
#[cfg(all(feature = "recipient", feature = "secp256k1"))]
#[test]
fn test_multi_recipient() {
let content_key = SymmetricKey::new();
let envelope = hello_envelope()
.encrypt_subject(&content_key)
.unwrap()
.add_recipient(&bob_public_key(), &content_key)
.add_recipient(&carol_public_key(), &content_key)
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'hasRecipient': SealedMessage
'hasRecipient': SealedMessage
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope = Envelope::from_ur(&ur).unwrap();
let bob_received_plaintext = received_envelope
.decrypt_subject_to_recipient(&bob_private_key())
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(bob_received_plaintext, PLAINTEXT_HELLO);
let carol_received_plaintext = received_envelope
.decrypt_subject_to_recipient(&carol_private_key())
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(carol_received_plaintext, PLAINTEXT_HELLO);
assert!(
received_envelope
.decrypt_subject_to_recipient(&alice_private_key())
.is_err()
);
}
#[cfg(all(feature = "signature", feature = "recipient"))]
#[test]
fn test_visible_signature_multi_recipient() {
let content_key = SymmetricKey::new();
let envelope = hello_envelope()
.add_signature(&alice_private_key())
.encrypt_subject(&content_key)
.unwrap()
.add_recipient(&bob_public_key(), &content_key)
.add_recipient(&carol_public_key(), &content_key)
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'hasRecipient': SealedMessage
'hasRecipient': SealedMessage
'signed': Signature
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope = Envelope::from_ur(&ur).unwrap();
let bob_received_plaintext = received_envelope
.verify_signature_from(&alice_public_key())
.unwrap()
.decrypt_subject_to_recipient(&bob_private_key())
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(bob_received_plaintext, PLAINTEXT_HELLO);
let carol_received_plaintext = received_envelope
.verify_signature_from(&alice_public_key())
.unwrap()
.decrypt_subject_to_recipient(&carol_private_key())
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(carol_received_plaintext, PLAINTEXT_HELLO);
assert!(
received_envelope
.decrypt_subject_to_recipient(&alice_private_key())
.is_err()
);
}
#[cfg(all(feature = "signature", feature = "recipient"))]
#[test]
fn test_hidden_signature_multi_recipient() {
let content_key = SymmetricKey::new();
let envelope = hello_envelope()
.add_signature(&alice_private_key())
.wrap()
.encrypt_subject(&content_key)
.unwrap()
.add_recipient(&bob_public_key(), &content_key)
.add_recipient(&carol_public_key(), &content_key)
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'hasRecipient': SealedMessage
'hasRecipient': SealedMessage
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope = Envelope::from_ur(&ur).unwrap();
let bob_received_plaintext = received_envelope
.decrypt_subject_to_recipient(&bob_private_key())
.unwrap()
.try_unwrap()
.unwrap()
.check_encoding()
.unwrap()
.verify_signature_from(&alice_public_key())
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(bob_received_plaintext, PLAINTEXT_HELLO);
let carol_received_plaintext = received_envelope
.decrypt_subject_to_recipient(&carol_private_key())
.unwrap()
.try_unwrap()
.unwrap()
.check_encoding()
.unwrap()
.verify_signature_from(&alice_public_key())
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(carol_received_plaintext, PLAINTEXT_HELLO);
assert!(
received_envelope
.decrypt_subject_to_recipient(&alice_private_key())
.is_err()
);
}
#[cfg(feature = "secret")]
#[test]
fn test_secret_1() {
use bc_components::KeyDerivationMethod;
bc_envelope::register_tags();
let bob_password = "correct horse battery staple";
let envelope = hello_envelope()
.lock(KeyDerivationMethod::HKDF, bob_password)
.unwrap();
envelope.check_encoding().unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'hasSecret': EncryptedKey(HKDF(SHA256))
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope = Envelope::from_ur(&ur).unwrap();
let bob_received_plaintext = received_envelope
.unlock(bob_password)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(bob_received_plaintext, PLAINTEXT_HELLO);
assert!(received_envelope.unlock("wrong password").is_err());
}
#[cfg(feature = "secret")]
#[test]
fn test_secret_2() {
use bc_components::KeyDerivationMethod;
bc_envelope::register_tags();
let bob_password = "correct horse battery staple";
let carol_password = "Able was I ere I saw Elba";
let gracy_password = "Madam, in Eden, I'm Adam";
let content_key = SymmetricKey::new();
let envelope = hello_envelope()
.encrypt_subject(&content_key)
.unwrap()
.add_secret(KeyDerivationMethod::HKDF, bob_password, &content_key)
.unwrap()
.add_secret(KeyDerivationMethod::Scrypt, carol_password, &content_key)
.unwrap()
.add_secret(KeyDerivationMethod::Argon2id, gracy_password, &content_key)
.unwrap()
.check_encoding()
.unwrap();
let ur = envelope.ur();
#[rustfmt::skip]
let expected_format = (indoc! {r#"
ENCRYPTED [
'hasSecret': EncryptedKey(Argon2id)
'hasSecret': EncryptedKey(HKDF(SHA256))
'hasSecret': EncryptedKey(Scrypt)
]
"#}).trim();
assert_actual_expected!(envelope.format(), expected_format);
let received_envelope = Envelope::from_ur(&ur).unwrap();
let bob_received_plaintext = received_envelope
.unlock_subject(bob_password)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(bob_received_plaintext, PLAINTEXT_HELLO);
let carol_received_plaintext = received_envelope
.unlock_subject(carol_password)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(carol_received_plaintext, PLAINTEXT_HELLO);
let gracy_received_plaintext = received_envelope
.unlock_subject(gracy_password)
.unwrap()
.check_encoding()
.unwrap()
.extract_subject::<String>()
.unwrap();
assert_eq!(gracy_received_plaintext, PLAINTEXT_HELLO);
assert!(received_envelope.unlock_subject("wrong password").is_err());
}