pub struct Bottle { /* private fields */ }Expand description
A Bottle is a layered message container with encryption and signatures.
Bottles support multiple layers of encryption (each for a different recipient) and multiple signatures (from different signers). The encryption layers are applied sequentially, with the outermost layer being the last one added.
§Example
use rust_bottle::*;
use rand::rngs::OsRng;
let message = b"Secret message";
let mut bottle = Bottle::new(message.to_vec());
// Encrypt to multiple recipients (layered encryption)
let rng = &mut OsRng;
let bob_key = X25519Key::generate(rng);
let charlie_key = X25519Key::generate(rng);
// First encryption (innermost)
bottle.encrypt(rng, &bob_key.public_key_bytes()).unwrap();
// Second encryption (outermost)
bottle.encrypt(rng, &charlie_key.public_key_bytes()).unwrap();
// Sign the bottle
let alice_key = Ed25519Key::generate(rng);
let alice_pub = alice_key.public_key_bytes();
bottle.sign(rng, &alice_key, &alice_pub).unwrap();
// Serialize for storage/transmission
let serialized = bottle.to_bytes().unwrap();Implementations§
Source§impl Bottle
impl Bottle
Sourcepub fn new(message: Vec<u8>) -> Self
pub fn new(message: Vec<u8>) -> Self
Create a new bottle with a message.
The message is initially unencrypted and unsigned. Encryption and
signatures can be added using the encrypt and sign methods.
§Arguments
message- The message payload to store in the bottle
§Example
use rust_bottle::Bottle;
let bottle = Bottle::new(b"Hello, world!".to_vec());
assert!(!bottle.is_encrypted());
assert!(!bottle.is_signed());Sourcepub fn message(&self) -> &[u8] ⓘ
pub fn message(&self) -> &[u8] ⓘ
Get the message payload.
If the bottle is encrypted, this returns the encrypted ciphertext
(outermost layer). Use Opener::open to decrypt.
§Returns
A reference to the message bytes (encrypted or plaintext)
Sourcepub fn is_encrypted(&self) -> bool
pub fn is_encrypted(&self) -> bool
Check if the bottle has any encryption layers.
§Returns
true if the bottle has one or more encryption layers, false otherwise
Sourcepub fn is_signed(&self) -> bool
pub fn is_signed(&self) -> bool
Check if the bottle has any signature layers.
§Returns
true if the bottle has one or more signatures, false otherwise
Sourcepub fn encryption_count(&self) -> usize
pub fn encryption_count(&self) -> usize
Get the number of encryption layers.
Each call to encrypt adds a new encryption layer. Layers are
applied sequentially, with the last added layer being the outermost.
§Returns
The number of encryption layers (0 if unencrypted)
Sourcepub fn encrypt<R: RngCore + CryptoRng>(
&mut self,
rng: &mut R,
public_key: &[u8],
) -> Result<()>
pub fn encrypt<R: RngCore + CryptoRng>( &mut self, rng: &mut R, public_key: &[u8], ) -> Result<()>
Encrypt the bottle to a public key.
This adds a new encryption layer. If the bottle is already encrypted, the existing ciphertext is encrypted again (layered encryption). Each layer can target a different recipient.
§Arguments
rng- A cryptographically secure random number generatorpublic_key- The recipient’s public key (X25519 or P-256 format)
§Returns
Ok(())if encryption succeedsErr(BottleError::Encryption)if encryption failsErr(BottleError::InvalidKeyType)if the key format is invalid
§Example
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();
assert!(bottle.is_encrypted());Sourcepub fn sign<R: RngCore>(
&mut self,
rng: &mut R,
signer: &dyn Sign,
public_key: &[u8],
) -> Result<()>
pub fn sign<R: RngCore>( &mut self, rng: &mut R, signer: &dyn Sign, public_key: &[u8], ) -> Result<()>
Sign the bottle with a private key.
This adds a new signature layer. Multiple signers can sign the same bottle by calling this method multiple times. The signature covers the message and all encryption layers.
§Arguments
rng- A random number generator (may be used for non-deterministic signing)signer- A signer implementing theSigntrait (e.g.,Ed25519Key,EcdsaP256Key)public_key- The signer’s public key (used for fingerprinting)
§Returns
Ok(())if signing succeedsErr(BottleError::VerifyFailed)if signing fails
§Example
use rust_bottle::*;
use rand::rngs::OsRng;
let mut bottle = Bottle::new(b"Message".to_vec());
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());Sourcepub fn set_metadata(&mut self, key: &str, value: &str)
pub fn set_metadata(&mut self, key: &str, value: &str)
Set metadata key-value pair.
Metadata is application-specific data stored with the bottle. It is not encrypted or signed, so it should not contain sensitive information.
§Arguments
key- Metadata keyvalue- Metadata value
§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");Sourcepub fn metadata(&self, key: &str) -> Option<&str>
pub fn metadata(&self, key: &str) -> Option<&str>
Get metadata value by key.
§Arguments
key- Metadata key to look up
§Returns
Some(&str)if the key existsNoneif the key is not found
§Example
use rust_bottle::Bottle;
let mut bottle = Bottle::new(b"Message".to_vec());
bottle.set_metadata("sender", "alice");
assert_eq!(bottle.metadata("sender"), Some("alice"));Sourcepub fn to_bytes(&self) -> Result<Vec<u8>>
pub fn to_bytes(&self) -> Result<Vec<u8>>
Serialize bottle to bytes using bincode.
The serialized format is binary and efficient. It includes all encryption layers, signatures, and metadata.
§Returns
Ok(Vec<u8>)- Serialized bottle bytesErr(BottleError::Serialization)- If serialization fails
§Example
use rust_bottle::Bottle;
let bottle = Bottle::new(b"Message".to_vec());
let bytes = bottle.to_bytes().unwrap();
let restored = Bottle::from_bytes(&bytes).unwrap();Sourcepub fn from_bytes(data: &[u8]) -> Result<Self>
pub fn from_bytes(data: &[u8]) -> Result<Self>
Deserialize bottle from bytes.
§Arguments
data- Serialized bottle bytes (fromto_bytes)
§Returns
Ok(Bottle)- Deserialized bottleErr(BottleError::Deserialization)- If deserialization fails
§Example
use rust_bottle::Bottle;
let bottle = Bottle::new(b"Message".to_vec());
let bytes = bottle.to_bytes().unwrap();
let restored = Bottle::from_bytes(&bytes).unwrap();
assert_eq!(bottle.message(), restored.message());