rust-bottle 0.2.3

Rust implementation of Bottle protocol - layered message containers with encryption and signatures
Documentation
use rand::rngs::OsRng;
use rust_bottle::*;

#[test]
fn test_bottle_creation() {
    let message = b"Hello, Bottle!";
    let bottle = Bottle::new(message.to_vec());
    assert_eq!(bottle.message(), message);
}

#[test]
fn test_bottle_encryption() {
    let message = b"Secret message";
    let mut bottle = Bottle::new(message.to_vec());

    // Generate a key pair for encryption
    let (public_key, private_key) = generate_test_keypair();

    // Encrypt the bottle
    let rng = &mut OsRng;
    bottle.encrypt(rng, &public_key).unwrap();

    // Verify it's encrypted
    assert!(bottle.is_encrypted());

    // Decrypt and verify message
    let opener = Opener::new();
    let decrypted = opener.open(&bottle, Some(&private_key)).unwrap();
    assert_eq!(decrypted, message);
}

#[test]
fn test_bottle_signing() {
    let message = b"Signed message";
    let mut bottle = Bottle::new(message.to_vec());

    // Generate a signing key pair
    let (public_key, signer) = generate_test_signing_keypair();

    // Sign the bottle
    let rng = &mut OsRng;
    bottle.sign(rng, &*signer, &public_key).unwrap();

    // Verify signature
    let opener = Opener::new();
    let info = opener.open_info(&bottle).unwrap();
    assert!(info.is_signed_by(&public_key));
}

#[test]
fn test_bottle_encryption_and_signing() {
    let message = b"Encrypted and signed message";
    let mut bottle = Bottle::new(message.to_vec());

    let (enc_pub, enc_priv) = generate_test_keypair();
    let (sig_pub, signer) = generate_test_signing_keypair();

    let rng = &mut OsRng;
    bottle.encrypt(rng, &enc_pub).unwrap();
    bottle.sign(rng, &*signer, &sig_pub).unwrap();

    let opener = Opener::new();
    let decrypted = opener.open(&bottle, Some(&enc_priv)).unwrap();
    assert_eq!(decrypted, message);

    let info = opener.open_info(&bottle).unwrap();
    assert!(info.is_signed_by(&sig_pub));
}

#[test]
fn test_bottle_layered_encryption() {
    let message = b"Multi-layer encrypted";
    let mut bottle = Bottle::new(message.to_vec());

    let (pub1, _priv1) = generate_test_keypair();
    let (pub2, _priv2) = generate_test_keypair();

    let rng = &mut OsRng;
    // Encrypt with key1 first (inner layer)
    bottle.encrypt(rng, &pub1).unwrap();
    // Encrypt with key2 second (outer layer)
    bottle.encrypt(rng, &pub2).unwrap();

    // Verify the structure - we have 2 encryption layers
    assert!(bottle.encryption_count() == 2);

    // Note: With layered encryption, each layer uses a different key
    // To decrypt, you'd need to decrypt with priv2 first (outermost), then priv1 (innermost)
    // The current implementation requires all keys to be provided, but for this test
    // we'll just verify the encryption structure is correct
    let opener = Opener::new();
    let info = opener.open_info(&bottle).unwrap();
    assert!(info.is_encrypted);
    assert_eq!(info.recipients.len(), 2);
}

#[test]
fn test_bottle_serialization() {
    let message = b"Serializable message";
    let bottle = Bottle::new(message.to_vec());

    let serialized = bottle.to_bytes().unwrap();
    let deserialized = Bottle::from_bytes(&serialized).unwrap();

    assert_eq!(bottle.message(), deserialized.message());
}

#[test]
fn test_bottle_with_metadata() {
    let message = b"Message with metadata";
    let mut bottle = Bottle::new(message.to_vec());
    bottle.set_metadata("key1", "value1");
    bottle.set_metadata("key2", "value2");

    assert_eq!(bottle.metadata("key1"), Some("value1"));
    assert_eq!(bottle.metadata("key2"), Some("value2"));
}

// Helper functions for tests
fn generate_test_keypair() -> (Vec<u8>, Vec<u8>) {
    let rng = &mut OsRng;
    let key = X25519Key::generate(rng);
    (key.public_key_bytes(), key.private_key_bytes())
}

fn generate_test_signing_keypair() -> (Vec<u8>, Box<dyn Sign>) {
    let rng = &mut OsRng;
    let key = Ed25519Key::generate(rng);
    let pub_key = key.public_key_bytes();
    (pub_key, Box::new(key))
}