This document provides comprehensive API documentation with detailed examples for every public function and method in the rust-bottle library.
- Bottle API
- Opener API
- Key Types API
- Post-Quantum Key Types API
- ECDH Encryption API
- IDCard API
- Keychain API
- Membership API
- Signing and Verification API
- Hash Functions API
- Utility Functions API
- Error Handling
The Bottle type is the core message container that supports layered encryption and multiple signatures.
Creates a new bottle with a message payload.
Example:
use rust_bottle::Bottle;
let message = b"Hello, world!".to_vec();
let bottle = Bottle::new(message);
// Initially unencrypted and unsigned
assert!(!bottle.is_encrypted());
assert!(!bottle.is_signed());Returns a reference to the message payload. If encrypted, returns the encrypted ciphertext.
Example:
use rust_bottle::Bottle;
let bottle = Bottle::new(b"Secret message".to_vec());
let message_ref = bottle.message();
assert_eq!(message_ref, b"Secret message");Checks if the bottle has any encryption layers.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
assert!(!bottle.is_encrypted());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
assert!(bottle.is_encrypted());Checks if the bottle has any signature layers.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
assert!(!bottle.is_signed());
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let pub_key = key.public_key_bytes();
bottle.sign(rng, &key, &pub_key).unwrap();
assert!(bottle.is_signed());Returns the number of encryption layers.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
assert_eq!(bottle.encryption_count(), 0);
let rng = &mut OsRng;
let key1 = X25519Key::generate(rng);
let key2 = X25519Key::generate(rng);
// Add first encryption layer
bottle.encrypt(rng, &key1.public_key_bytes()).unwrap();
assert_eq!(bottle.encryption_count(), 1);
// Add second encryption layer
bottle.encrypt(rng, &key2.public_key_bytes()).unwrap();
assert_eq!(bottle.encryption_count(), 2);Encrypts the bottle to a public key, adding a new encryption layer.
Example - Single Encryption:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Secret message".to_vec());
let rng = &mut OsRng;
let recipient_key = X25519Key::generate(rng);
// Encrypt to recipient
bottle.encrypt(rng, &recipient_key.public_key_bytes()).unwrap();
assert!(bottle.is_encrypted());Example - Layered Encryption (Multiple Recipients):
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Multi-recipient message".to_vec());
let rng = &mut OsRng;
// Generate keys for multiple recipients
let alice_key = X25519Key::generate(rng);
let bob_key = X25519Key::generate(rng);
let charlie_key = X25519Key::generate(rng);
// Encrypt to each recipient (creates layered encryption)
bottle.encrypt(rng, &alice_key.public_key_bytes()).unwrap();
bottle.encrypt(rng, &bob_key.public_key_bytes()).unwrap();
bottle.encrypt(rng, &charlie_key.public_key_bytes()).unwrap();
assert_eq!(bottle.encryption_count(), 3);Example - Using P-256 Keys:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"P-256 encrypted message".to_vec());
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
assert!(bottle.is_encrypted());Bottle::sign<R: RngCore>(&mut self, rng: &mut R, signer: &dyn Sign, public_key: &[u8]) -> Result<()>
Signs the bottle with a private key, adding a new signature layer.
Example - Single Signature:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Signed message".to_vec());
let rng = &mut OsRng;
let signer_key = Ed25519Key::generate(rng);
let pub_key = signer_key.public_key_bytes();
bottle.sign(rng, &signer_key, &pub_key).unwrap();
assert!(bottle.is_signed());Example - Multiple Signatures:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Multi-signed message".to_vec());
let rng = &mut OsRng;
// Generate keys for multiple signers
let alice_key = Ed25519Key::generate(rng);
let bob_key = EcdsaP256Key::generate(rng);
let charlie_key = Ed25519Key::generate(rng);
// Each signer signs the bottle
bottle.sign(rng, &alice_key, &alice_key.public_key_bytes()).unwrap();
bottle.sign(rng, &bob_key, &bob_key.public_key_bytes()).unwrap();
bottle.sign(rng, &charlie_key, &charlie_key.public_key_bytes()).unwrap();
assert!(bottle.is_signed());
// Verify signatures
let opener = Opener::new();
let info = opener.open_info(&bottle).unwrap();
assert_eq!(info.signers.len(), 3);Example - Encrypted and Signed Bottle:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Encrypted and signed".to_vec());
let rng = &mut OsRng;
// Generate keys
let encryption_key = X25519Key::generate(rng);
let signing_key = Ed25519Key::generate(rng);
let signing_pub = signing_key.public_key_bytes();
// Encrypt first
bottle.encrypt(rng, &encryption_key.public_key_bytes()).unwrap();
// Then sign
bottle.sign(rng, &signing_key, &signing_pub).unwrap();
assert!(bottle.is_encrypted());
assert!(bottle.is_signed());Sets a metadata key-value pair. Metadata is not encrypted or signed.
Example:
use rust_bottle::Bottle;
let mut bottle = Bottle::new(b"Message".to_vec());
bottle.set_metadata("sender", "alice@example.com");
bottle.set_metadata("timestamp", "2024-01-01T00:00:00Z");
bottle.set_metadata("subject", "Important message");
bottle.set_metadata("priority", "high");
// Retrieve metadata
assert_eq!(bottle.metadata("sender"), Some("alice@example.com"));
assert_eq!(bottle.metadata("timestamp"), Some("2024-01-01T00:00:00Z"));Retrieves a metadata value by key.
Example:
use rust_bottle::Bottle;
let mut bottle = Bottle::new(b"Message".to_vec());
bottle.set_metadata("sender", "alice");
match bottle.metadata("sender") {
Some(value) => println!("Sender: {}", value),
None => println!("No sender metadata"),
}
// Non-existent key returns None
assert_eq!(bottle.metadata("nonexistent"), None);Serializes the bottle to bytes using bincode.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
// Serialize for storage or transmission
let serialized = bottle.to_bytes().unwrap();
// Save to file, send over network, etc.
// std::fs::write("bottle.bin", &serialized).unwrap();Deserializes a bottle from bytes.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
// Create and serialize a bottle
let mut bottle = Bottle::new(b"Message".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
let serialized = bottle.to_bytes().unwrap();
// Deserialize
let deserialized = Bottle::from_bytes(&serialized).unwrap();
assert_eq!(bottle.message(), deserialized.message());
assert_eq!(bottle.encryption_count(), deserialized.encryption_count());The Opener type provides methods to decrypt and inspect bottles.
Creates a new opener instance.
Example:
use rust_bottle::Opener;
let opener = Opener::new();Opens a bottle, decrypting all encryption layers if needed.
Example - Opening Unencrypted Bottle:
use rust_bottle::*;
let bottle = Bottle::new(b"Plain message".to_vec());
let opener = Opener::new();
// No key needed for unencrypted bottles
let message = opener.open(&bottle, None).unwrap();
assert_eq!(message, b"Plain message");Example - Opening Encrypted Bottle:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Secret message".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
// Encrypt
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
// Decrypt
let opener = Opener::new();
let decrypted = opener.open(&bottle, Some(&key.private_key_bytes())).unwrap();
assert_eq!(decrypted, b"Secret message");Example - Opening Layered Encrypted Bottle:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Layered message".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
// Add multiple encryption layers
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
// Decrypt all layers
let opener = Opener::new();
let decrypted = opener.open(&bottle, Some(&key.private_key_bytes())).unwrap();
assert_eq!(decrypted, b"Layered message");Example - Error Handling:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Secret".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
let opener = Opener::new();
// Wrong key fails
let wrong_key = X25519Key::generate(rng);
match opener.open(&bottle, Some(&wrong_key.private_key_bytes())) {
Ok(_) => panic!("Should have failed"),
Err(e) => println!("Decryption failed: {:?}", e),
}
// Missing key for encrypted bottle fails
match opener.open(&bottle, None) {
Ok(_) => panic!("Should have failed"),
Err(BottleError::NoAppropriateKey) => println!("Correct error"),
Err(e) => panic!("Wrong error: {:?}", e),
}Gets information about a bottle without decrypting it.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
let rng = &mut OsRng;
// Encrypt
let enc_key = X25519Key::generate(rng);
bottle.encrypt(rng, &enc_key.public_key_bytes()).unwrap();
// Sign
let sig_key = Ed25519Key::generate(rng);
let sig_pub = sig_key.public_key_bytes();
bottle.sign(rng, &sig_key, &sig_pub).unwrap();
// Get info without decrypting
let opener = Opener::new();
let info = opener.open_info(&bottle).unwrap();
assert!(info.is_encrypted);
assert!(info.is_signed);
assert_eq!(info.recipients.len(), 1);
assert_eq!(info.signers.len(), 1);Checks if the bottle is signed by a specific public key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
let rng = &mut OsRng;
let signer_key = Ed25519Key::generate(rng);
let pub_key = signer_key.public_key_bytes();
bottle.sign(rng, &signer_key, &pub_key).unwrap();
let opener = Opener::new();
let info = opener.open_info(&bottle).unwrap();
// Check if signed by specific key
assert!(info.is_signed_by(&pub_key));
// Different key returns false
let other_key = Ed25519Key::generate(rng);
assert!(!info.is_signed_by(&other_key.public_key_bytes()));The library provides classical key types: EcdsaP256Key, Ed25519Key, and X25519Key. Post-quantum key types are available with feature flags (see Post-Quantum Key Types API).
Generates a new ECDSA P-256 key pair.
Example:
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);Gets the public key in SEC1 uncompressed format (65 bytes).
Example:
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
let pub_key = key.public_key_bytes();
assert_eq!(pub_key.len(), 65); // SEC1 uncompressed formatGets the private key bytes (32 bytes).
Example:
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
let priv_key = key.private_key_bytes();
assert_eq!(priv_key.len(), 32);Reconstructs a key pair from private key bytes.
Example:
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let original = EcdsaP256Key::generate(rng);
let priv_bytes = original.private_key_bytes();
// Reconstruct from private key
let restored = EcdsaP256Key::from_private_key_bytes(&priv_bytes).unwrap();
assert_eq!(original.public_key_bytes(), restored.public_key_bytes());Generates a new Ed25519 key pair.
Example:
use rust_bottle::keys::Ed25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);Gets the public key bytes (32 bytes).
Example:
use rust_bottle::keys::Ed25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let pub_key = key.public_key_bytes();
assert_eq!(pub_key.len(), 32);Gets the private key bytes (32 bytes).
Example:
use rust_bottle::keys::Ed25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let priv_key = key.private_key_bytes();
assert_eq!(priv_key.len(), 32);Reconstructs a key pair from private key bytes.
Example:
use rust_bottle::keys::Ed25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let original = Ed25519Key::generate(rng);
let priv_bytes = original.private_key_bytes();
let restored = Ed25519Key::from_private_key_bytes(&priv_bytes).unwrap();
assert_eq!(original.public_key_bytes(), restored.public_key_bytes());Generates a new X25519 key pair for ECDH encryption.
Example:
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = X25519Key::generate(rng);Gets the public key bytes (32 bytes).
Example:
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
let pub_key = key.public_key_bytes();
assert_eq!(pub_key.len(), 32);Gets the private key bytes (32 bytes).
Example:
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
let priv_key = key.private_key_bytes();
assert_eq!(priv_key.len(), 32);Reconstructs a key pair from private key bytes.
Example:
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let original = X25519Key::generate(rng);
let priv_bytes = original.private_key_bytes();
let restored = X25519Key::from_private_key_bytes(&priv_bytes).unwrap();
assert_eq!(original.public_key_bytes(), restored.public_key_bytes());Direct ECDH encryption functions for encrypting data to public keys. Supports both classical and post-quantum key types with automatic detection.
ecdh_encrypt<R: RngCore + CryptoRng>(rng: &mut R, plaintext: &[u8], public_key: &[u8]) -> Result<Vec<u8>>
Encrypts plaintext to a public key using ECDH with automatic key type detection.
Example - X25519 Encryption:
use rust_bottle::ecdh::ecdh_encrypt;
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let plaintext = b"Secret message";
let rng = &mut OsRng;
// Generate keys
let alice_key = X25519Key::generate(rng);
let bob_key = X25519Key::generate(rng);
// Alice encrypts to Bob
let ciphertext = ecdh_encrypt(rng, plaintext, &bob_key.public_key_bytes()).unwrap();
// Bob decrypts
use rust_bottle::ecdh::ecdh_decrypt;
let decrypted = ecdh_decrypt(&ciphertext, &bob_key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);Example - P-256 Encryption:
use rust_bottle::ecdh::ecdh_encrypt;
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
let plaintext = b"P-256 encrypted message";
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
let ciphertext = ecdh_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();
use rust_bottle::ecdh::ecdh_decrypt;
let decrypted = ecdh_decrypt(&ciphertext, &key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);Decrypts ciphertext using a private key with automatic key type detection. Supports X25519, P-256, ML-KEM-768, and ML-KEM-1024.
Example - Classical Keys:
use rust_bottle::ecdh::{ecdh_encrypt, ecdh_decrypt};
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
let plaintext = b"Message to encrypt";
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
// Encrypt
let ciphertext = ecdh_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();
// Decrypt
let decrypted = ecdh_decrypt(&ciphertext, &key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);Example - Post-Quantum Keys:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::{ecdh_encrypt, ecdh_decrypt};
use rust_bottle::keys::MlKem768Key;
use rand::rngs::OsRng;
let plaintext = b"Post-quantum encrypted";
let rng = &mut OsRng;
let key = MlKem768Key::generate(rng);
// Automatically detects ML-KEM-768 from key size
let ciphertext = ecdh_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();
let decrypted = ecdh_decrypt(&ciphertext, &key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);ecdh_encrypt_p256<R: RngCore + CryptoRng>(rng: &mut R, plaintext: &[u8], public_key: &PublicKey) -> Result<Vec<u8>>
Encrypts using P-256 ECDH (lower-level function).
Example:
use rust_bottle::ecdh::ecdh_encrypt_p256;
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
use p256::PublicKey;
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
let pub_key = PublicKey::from_sec1_bytes(&key.public_key_bytes()).unwrap();
let plaintext = b"P-256 encrypted";
let ciphertext = ecdh_encrypt_p256(rng, plaintext, &pub_key).unwrap();Decrypts using P-256 ECDH (lower-level function).
Example:
use rust_bottle::ecdh::{ecdh_encrypt_p256, ecdh_decrypt_p256};
use rust_bottle::keys::EcdsaP256Key;
use rand::rngs::OsRng;
use p256::{PublicKey, SecretKey};
let rng = &mut OsRng;
let key = EcdsaP256Key::generate(rng);
let pub_key = PublicKey::from_sec1_bytes(&key.public_key_bytes()).unwrap();
let priv_key = SecretKey::from_bytes(&key.private_key_bytes().as_slice().into()).unwrap();
let plaintext = b"Message";
let ciphertext = ecdh_encrypt_p256(rng, plaintext, &pub_key).unwrap();
let decrypted = ecdh_decrypt_p256(&ciphertext, &priv_key).unwrap();
assert_eq!(decrypted, plaintext);ecdh_encrypt_x25519<R: RngCore>(rng: &mut R, plaintext: &[u8], public_key: &X25519PublicKey) -> Result<Vec<u8>>
Encrypts using X25519 ECDH (lower-level function).
Example:
use rust_bottle::ecdh::ecdh_encrypt_x25519;
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
use x25519_dalek::PublicKey;
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
let pub_key_bytes: [u8; 32] = key.public_key_bytes().try_into().unwrap();
let pub_key = PublicKey::from(pub_key_bytes);
let plaintext = b"X25519 encrypted";
let ciphertext = ecdh_encrypt_x25519(rng, plaintext, &pub_key).unwrap();Decrypts using X25519 ECDH (lower-level function).
Example:
use rust_bottle::ecdh::{ecdh_encrypt_x25519, ecdh_decrypt_x25519};
use rust_bottle::keys::X25519Key;
use rand::rngs::OsRng;
use x25519_dalek::PublicKey;
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
let pub_key_bytes: [u8; 32] = key.public_key_bytes().try_into().unwrap();
let pub_key = PublicKey::from(pub_key_bytes);
let priv_key_bytes: [u8; 32] = key.private_key_bytes().try_into().unwrap();
let plaintext = b"Message";
let ciphertext = ecdh_encrypt_x25519(rng, plaintext, &pub_key).unwrap();
let decrypted = ecdh_decrypt_x25519(&ciphertext, &priv_key_bytes).unwrap();
assert_eq!(decrypted, plaintext);mlkem768_encrypt<R: RngCore + CryptoRng>(rng: &mut R, plaintext: &[u8], public_key: &[u8]) -> Result<Vec<u8>>
Encrypts plaintext using ML-KEM-768 key encapsulation. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::mlkem768_encrypt;
use rust_bottle::keys::MlKem768Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = MlKem768Key::generate(rng);
let plaintext = b"Secret message";
let ciphertext = mlkem768_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();Decrypts ciphertext encrypted with ML-KEM-768. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::{mlkem768_encrypt, mlkem768_decrypt};
use rust_bottle::keys::MlKem768Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = MlKem768Key::generate(rng);
let plaintext = b"Secret message";
let ciphertext = mlkem768_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();
let decrypted = mlkem768_decrypt(&ciphertext, &key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);mlkem1024_encrypt<R: RngCore + CryptoRng>(rng: &mut R, plaintext: &[u8], public_key: &[u8]) -> Result<Vec<u8>>
Encrypts plaintext using ML-KEM-1024 key encapsulation. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::mlkem1024_encrypt;
use rust_bottle::keys::MlKem1024Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = MlKem1024Key::generate(rng);
let plaintext = b"Secret message";
let ciphertext = mlkem1024_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();Decrypts ciphertext encrypted with ML-KEM-1024. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::{mlkem1024_encrypt, mlkem1024_decrypt};
use rust_bottle::keys::MlKem1024Key;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = MlKem1024Key::generate(rng);
let plaintext = b"Secret message";
let ciphertext = mlkem1024_encrypt(rng, plaintext, &key.public_key_bytes()).unwrap();
let decrypted = mlkem1024_decrypt(&ciphertext, &key.private_key_bytes()).unwrap();
assert_eq!(decrypted, plaintext);hybrid_encrypt_mlkem768_x25519<R: RngCore + CryptoRng>(rng: &mut R, plaintext: &[u8], mlkem_pub: &[u8], x25519_pub: &[u8]) -> Result<Vec<u8>>
Hybrid encryption combining ML-KEM-768 and X25519 for both post-quantum and classical security. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::hybrid_encrypt_mlkem768_x25519;
use rust_bottle::keys::{MlKem768Key, X25519Key};
use rand::rngs::OsRng;
let rng = &mut OsRng;
let mlkem_key = MlKem768Key::generate(rng);
let x25519_key = X25519Key::generate(rng);
let plaintext = b"Hybrid encrypted";
let ciphertext = hybrid_encrypt_mlkem768_x25519(
rng,
plaintext,
&mlkem_key.public_key_bytes(),
&x25519_key.public_key_bytes(),
).unwrap();hybrid_decrypt_mlkem768_x25519(ciphertext: &[u8], mlkem_sec: &[u8], x25519_sec: &[u8; 32]) -> Result<Vec<u8>>
Decrypts hybrid-encrypted ciphertext. Tries ML-KEM first, falls back to X25519. Requires ml-kem feature.
Example:
#[cfg(feature = "ml-kem")]
use rust_bottle::ecdh::{hybrid_encrypt_mlkem768_x25519, hybrid_decrypt_mlkem768_x25519};
use rust_bottle::keys::{MlKem768Key, X25519Key};
use rand::rngs::OsRng;
let rng = &mut OsRng;
let mlkem_key = MlKem768Key::generate(rng);
let x25519_key = X25519Key::generate(rng);
let plaintext = b"Hybrid encrypted";
let ciphertext = hybrid_encrypt_mlkem768_x25519(
rng,
plaintext,
&mlkem_key.public_key_bytes(),
&x25519_key.public_key_bytes(),
).unwrap();
let mlkem_sec = mlkem_key.private_key_bytes();
let x25519_sec: [u8; 32] = x25519_key.private_key_bytes().try_into().unwrap();
let decrypted = hybrid_decrypt_mlkem768_x25519(&ciphertext, &mlkem_sec, &x25519_sec).unwrap();
assert_eq!(decrypted, plaintext);IDCards allow entities to declare keys with specific purposes and manage key lifecycles.
Creates a new IDCard for a public key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let idcard = IDCard::new(&key.public_key_bytes());Sets a metadata key-value pair.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let mut idcard = IDCard::new(&key.public_key_bytes());
idcard.set_metadata("name", "Alice");
idcard.set_metadata("email", "alice@example.com");
idcard.set_metadata("organization", "Example Corp");
idcard.set_metadata("department", "Engineering");Gets a metadata value by key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let mut idcard = IDCard::new(&key.public_key_bytes());
idcard.set_metadata("name", "Alice");
assert_eq!(idcard.metadata("name"), Some("Alice"));
assert_eq!(idcard.metadata("nonexistent"), None);Sets the purposes for a key (e.g., "sign", "decrypt").
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let primary_key = Ed25519Key::generate(rng);
let mut idcard = IDCard::new(&primary_key.public_key_bytes());
// Set purposes for primary key
idcard.set_key_purposes(&primary_key.public_key_bytes(), &["sign", "decrypt"]);
// Add a dedicated signing key
let signing_key = Ed25519Key::generate(rng);
idcard.set_key_purposes(&signing_key.public_key_bytes(), &["sign"]);
// Add a dedicated encryption key
let encryption_key = X25519Key::generate(rng);
idcard.set_key_purposes(&encryption_key.public_key_bytes(), &["decrypt"]);Sets the expiration duration for a key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
use std::time::Duration;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let mut idcard = IDCard::new(&key.public_key_bytes());
// Set key to expire in 1 year
idcard.set_key_duration(&key.public_key_bytes(), Duration::from_secs(365 * 24 * 3600));
// Set key to expire in 30 days
let temp_key = Ed25519Key::generate(rng);
idcard.set_key_duration(&temp_key.public_key_bytes(), Duration::from_secs(30 * 24 * 3600));Tests if a key has a specific purpose and is not expired.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let signing_key = Ed25519Key::generate(rng);
let encryption_key = X25519Key::generate(rng);
let mut idcard = IDCard::new(&signing_key.public_key_bytes());
idcard.set_key_purposes(&signing_key.public_key_bytes(), &["sign"]);
idcard.set_key_purposes(&encryption_key.public_key_bytes(), &["decrypt"]);
// Test purposes
assert!(idcard.test_key_purpose(&signing_key.public_key_bytes(), "sign").is_ok());
assert!(idcard.test_key_purpose(&encryption_key.public_key_bytes(), "decrypt").is_ok());
// Wrong purpose fails
assert!(idcard.test_key_purpose(&signing_key.public_key_bytes(), "decrypt").is_err());
assert!(idcard.test_key_purpose(&encryption_key.public_key_bytes(), "sign").is_err());Gets all key fingerprints that have a specific purpose and are not expired.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key1 = Ed25519Key::generate(rng);
let key2 = Ed25519Key::generate(rng);
let key3 = X25519Key::generate(rng);
let mut idcard = IDCard::new(&key1.public_key_bytes());
idcard.set_key_purposes(&key1.public_key_bytes(), &["sign"]);
idcard.set_key_purposes(&key2.public_key_bytes(), &["sign"]);
idcard.set_key_purposes(&key3.public_key_bytes(), &["decrypt"]);
// Get all signing keys
let sign_keys = idcard.get_keys("sign");
assert_eq!(sign_keys.len(), 2);
// Get all decryption keys
let decrypt_keys = idcard.get_keys("decrypt");
assert_eq!(decrypt_keys.len(), 2); // Includes primary keyUpdates the list of group memberships.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let group_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_idcard = IDCard::new(&group_key.public_key_bytes());
// Create a membership
let mut membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
membership.set_info("role", "member");
let signed_membership = membership.sign(rng, &group_key).unwrap();
// Add membership to member's IDCard
let mut member_idcard = IDCard::new(&member_key.public_key_bytes());
member_idcard.update_groups(vec![signed_membership]);Signs the IDCard and returns the serialized signed IDCard.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let mut idcard = IDCard::new(&key.public_key_bytes());
idcard.set_metadata("name", "Alice");
idcard.set_key_purposes(&key.public_key_bytes(), &["sign", "decrypt"]);
// Sign the IDCard
let signed_bytes = idcard.sign(rng, &key).unwrap();
// The IDCard is now signed
assert!(idcard.signature.is_some());Serializes the IDCard to bytes.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let idcard = IDCard::new(&key.public_key_bytes());
let serialized = idcard.to_bytes().unwrap();Deserializes an IDCard from bytes.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let idcard = IDCard::new(&key.public_key_bytes());
let serialized = idcard.to_bytes().unwrap();
let restored = IDCard::from_bytes(&serialized).unwrap();Alias for from_bytes (for compatibility with gobottle).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let idcard = IDCard::new(&key.public_key_bytes());
let serialized = idcard.to_bytes().unwrap();
let restored = IDCard::unmarshal_binary(&serialized).unwrap();Keychains provide secure storage for private keys.
Creates a new empty keychain.
Example:
use rust_bottle::Keychain;
let keychain = Keychain::new();Adds a key to the keychain.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let ed25519_key = Ed25519Key::generate(rng);
let ecdsa_key = EcdsaP256Key::generate(rng);
let x25519_key = X25519Key::generate(rng);
keychain.add_key(ed25519_key);
keychain.add_key(ecdsa_key);
keychain.add_key(x25519_key);Adds multiple keys of the same type to the keychain.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let key1 = Ed25519Key::generate(rng);
let key2 = Ed25519Key::generate(rng);
let key3 = Ed25519Key::generate(rng);
keychain.add_keys(vec![key1, key2, key3]);Gets a key by its public key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let pub_key = key.public_key_bytes();
keychain.add_key(key);
let retrieved = keychain.get_key(&pub_key).unwrap();
assert_eq!(retrieved.public_key(), pub_key);Gets a signer by its public key (alias for get_key).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let pub_key = key.public_key_bytes();
keychain.add_key(key);
let signer = keychain.get_signer(&pub_key).unwrap();Keychain::sign<R: RngCore>(&self, rng: &mut R, public_key: &[u8], message: &[u8]) -> Result<Vec<u8>>
Signs a message with a specific key from the keychain.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let pub_key = key.public_key_bytes();
keychain.add_key(key);
let message = b"Message to sign";
let signature = keychain.sign(rng, &pub_key, message).unwrap();Iterates over all signers in the keychain.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut keychain = Keychain::new();
let rng = &mut OsRng;
let key1 = Ed25519Key::generate(rng);
let key2 = EcdsaP256Key::generate(rng);
let key3 = Ed25519Key::generate(rng);
keychain.add_key(key1);
keychain.add_key(key2);
keychain.add_key(key3);
// Iterate over all keys
for signer in keychain.signers() {
let pub_key = signer.public_key();
let fingerprint = signer.fingerprint();
println!("Key: {:?}, Fingerprint: {:?}", pub_key, fingerprint);
}Memberships provide cryptographically signed group affiliations.
Creates a new membership linking a member to a group.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let membership = Membership::new(&member_idcard, &group_key.public_key_bytes());Sets information about the membership (e.g., role, department).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let mut membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
membership.set_info("role", "admin");
membership.set_info("department", "Engineering");
membership.set_info("joined", "2024-01-01");
membership.set_info("level", "senior");Gets information value by key.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let mut membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
membership.set_info("role", "admin");
assert_eq!(membership.info("role"), Some("admin"));
assert_eq!(membership.info("nonexistent"), None);Signs the membership and returns the serialized signed membership.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let mut membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
membership.set_info("role", "admin");
// Group owner signs the membership
let signed_bytes = membership.sign(rng, &group_key).unwrap();Verifies the membership signature (simplified implementation).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let group_idcard = IDCard::new(&group_key.public_key_bytes());
let mut membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
membership.sign(rng, &group_key).unwrap();
// Verify membership
assert!(membership.verify(&group_idcard).is_ok());Serializes the membership to bytes.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
let serialized = membership.to_bytes().unwrap();Deserializes a membership from bytes.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let member_key = Ed25519Key::generate(rng);
let member_idcard = IDCard::new(&member_key.public_key_bytes());
let group_key = Ed25519Key::generate(rng);
let membership = Membership::new(&member_idcard, &group_key.public_key_bytes());
let serialized = membership.to_bytes().unwrap();
let restored = Membership::from_bytes(&serialized).unwrap();The Sign and Verify traits provide generic signing and verification operations.
Signs a message (trait method).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let message = b"Message to sign";
let signature = key.sign(rng, message).unwrap();Verifies a signature (trait method).
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let message = b"Message to sign";
let signature = key.sign(rng, message).unwrap();
assert!(key.verify(message, &signature).is_ok());
// Wrong message fails
assert!(key.verify(b"Different message", &signature).is_err());Generic sign function.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let message = b"Message";
let signature = rust_bottle::sign(rng, &key, message).unwrap();Generic verify function.
Example:
use rust_bottle::*;
use rand::rngs::OsRng;
let rng = &mut OsRng;
let key = Ed25519Key::generate(rng);
let message = b"Message";
let signature = key.sign(rng, message).unwrap();
assert!(rust_bottle::verify(&key, message, &signature).is_ok());The library provides various hashing functions for SHA-2 and SHA-3.
Hashes data using SHA-256.
Example:
use rust_bottle::hash::sha256;
let data = b"Hello, world!";
let hash = sha256(data);
assert_eq!(hash.len(), 32);
// Used for key fingerprinting
let key_bytes = b"public key bytes";
let fingerprint = sha256(key_bytes);Hashes data using SHA-384.
Example:
use rust_bottle::hash::sha384;
let data = b"Hello, world!";
let hash = sha384(data);
assert_eq!(hash.len(), 48);Hashes data using SHA-512.
Example:
use rust_bottle::hash::sha512;
let data = b"Hello, world!";
let hash = sha512(data);
assert_eq!(hash.len(), 64);Hashes data using SHA3-256.
Example:
use rust_bottle::hash::sha3_256;
let data = b"Hello, world!";
let hash = sha3_256(data);
assert_eq!(hash.len(), 32);Hashes data using SHA3-384.
Example:
use rust_bottle::hash::sha3_384;
let data = b"Hello, world!";
let hash = sha3_384(data);
assert_eq!(hash.len(), 48);Hashes data using SHA3-512.
Example:
use rust_bottle::hash::sha3_512;
let data = b"Hello, world!";
let hash = sha3_512(data);
assert_eq!(hash.len(), 64);Generic hash function that works with any Digest type.
Example:
use rust_bottle::hash::hash;
use sha2::Sha256;
let data = b"Hello, world!";
let hash = hash::<Sha256>(data);
assert_eq!(hash.len(), 32);Applies hashing multiple times.
Example:
use rust_bottle::hash::multi_hash;
use sha2::Sha256;
let data = b"Hello, world!";
let hash = multi_hash::<Sha256>(data, 3); // Hash 3 timesSecurely clears sensitive data from memory.
Example:
use rust_bottle::utils::mem_clr;
let mut sensitive = vec![1, 2, 3, 4, 5];
mem_clr(&mut sensitive);
// sensitive is now all zerosAll operations return Result<T, BottleError>. The BottleError enum covers all error conditions.
BottleError::NoAppropriateKey- No key available for decryptionBottleError::VerifyFailed- Signature verification failedBottleError::KeyNotFound- Key not found in keychain/IDCardBottleError::KeyUnfit- Key not authorized for the operationBottleError::InvalidKeyType- Invalid key formatBottleError::Serialization- Serialization errorBottleError::Deserialization- Deserialization errorBottleError::Encryption- Encryption errorBottleError::Decryption- Decryption errorBottleError::InvalidFormat- Invalid data formatBottleError::UnsupportedAlgorithm- Algorithm not supported
Example - Error Handling:
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
let rng = &mut OsRng;
let key = X25519Key::generate(rng);
bottle.encrypt(rng, &key.public_key_bytes()).unwrap();
let opener = Opener::new();
// Handle errors properly
match opener.open(&bottle, None) {
Ok(message) => println!("Decrypted: {:?}", message),
Err(BottleError::NoAppropriateKey) => println!("No key provided"),
Err(BottleError::Decryption(e)) => println!("Decryption failed: {}", e),
Err(e) => println!("Other error: {:?}", e),
}Here's a complete example showing Alice and Bob communicating securely:
use rust_bottle::*;
use rand::rngs::OsRng;
fn main() -> Result<()> {
let rng = &mut OsRng;
// Alice sets up
let alice_signing_key = Ed25519Key::generate(rng);
let alice_encryption_key = X25519Key::generate(rng);
let alice_idcard = IDCard::new(&alice_signing_key.public_key_bytes());
alice_idcard.set_metadata("name", "Alice");
alice_idcard.set_key_purposes(&alice_signing_key.public_key_bytes(), &["sign"]);
alice_idcard.set_key_purposes(&alice_encryption_key.public_key_bytes(), &["decrypt"]);
// Bob sets up
let bob_signing_key = Ed25519Key::generate(rng);
let bob_encryption_key = X25519Key::generate(rng);
let bob_idcard = IDCard::new(&bob_signing_key.public_key_bytes());
bob_idcard.set_metadata("name", "Bob");
bob_idcard.set_key_purposes(&bob_signing_key.public_key_bytes(), &["sign"]);
bob_idcard.set_key_purposes(&bob_encryption_key.public_key_bytes(), &["decrypt"]);
// Alice creates and sends a message
let message = b"Hello, Bob! This is a secret message.";
let mut bottle = Bottle::new(message.to_vec());
// Encrypt to Bob
bottle.encrypt(rng, &bob_encryption_key.public_key_bytes())?;
// Sign with Alice's key
bottle.sign(rng, &alice_signing_key, &alice_signing_key.public_key_bytes())?;
// Add metadata
bottle.set_metadata("from", "alice@example.com");
bottle.set_metadata("to", "bob@example.com");
bottle.set_metadata("subject", "Secret message");
// Serialize for transmission
let serialized = bottle.to_bytes()?;
// Bob receives and processes the message
let received_bottle = Bottle::from_bytes(&serialized)?;
// Check who signed it
let opener = Opener::new();
let info = opener.open_info(&received_bottle)?;
assert!(info.is_signed_by(&alice_signing_key.public_key_bytes()));
// Decrypt
let decrypted = opener.open(&received_bottle, Some(&bob_encryption_key.private_key_bytes()))?;
assert_eq!(decrypted, message);
println!("Message received: {:?}", String::from_utf8_lossy(&decrypted));
println!("From: {}", received_bottle.metadata("from").unwrap());
println!("Subject: {}", received_bottle.metadata("subject").unwrap());
Ok(())
}This comprehensive API reference covers all public functions and methods in the rust-bottle library with detailed, working examples.