diff --git a/aead/src/lib.rs b/aead/src/lib.rs index 856819b6b..5713cc041 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -7,7 +7,7 @@ extern crate alloc; pub use generic_array; use alloc::vec::Vec; -use generic_array::{GenericArray, ArrayLength, typenum::Unsigned}; +use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Error; @@ -33,22 +33,46 @@ pub trait Aead { /// ciphertext vs. a plaintext. type CiphertextOverhead: ArrayLength + Unsigned; - /// Encrypt the given plaintext slice, and return the resulting ciphertext - /// as a vector of bytes. - fn encrypt( + /// Encrypt the given plaintext payload, and return the resulting + /// ciphertext as a vector of bytes. + /// + /// The `Payload` type can be used to provide Additional Associated Data + /// (AAD) along with the message: this is an optional bytestring which is + /// not encrypted, but *is* authenticated along with the message. Failure + /// to pass the same AAD that was used during encryption will cause + /// decryption to fail, which is useful if you would like to "bind" the + /// ciphertext to some other identifier, like a digital signature key + /// or other identifier. + /// + /// If you don't care about AAD and just want to encrypt a plaintext + /// message, `&[u8]` will automatically be coerced into a `Payload`: + /// + /// ```nobuild + /// let plaintext = b"Top secret message, handle with care"; + /// let ciphertext = cipher.encrypt(nonce, plaintext); + /// ``` + fn encrypt<'msg, 'aad>( &mut self, - additional_data: &[u8], nonce: &GenericArray, - plaintext: &[u8] + plaintext: impl Into>, ) -> Result, Error>; /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. - fn decrypt( + /// + /// See notes on `Aead::encrypt()` about allowable message payloads and + /// Associated Additional Data (AAD). + /// + /// If you have no AAD, you can call this as follows: + /// + /// ```nobuild + /// let ciphertext = b"..."; + /// let plaintext = cipher.decrypt(nonce, ciphertext)?; + /// ``` + fn decrypt<'msg, 'aad>( &mut self, - additional_data: &[u8], nonce: &GenericArray, - ciphertext: &[u8] + ciphertext: impl Into>, ) -> Result, Error>; } @@ -65,20 +89,24 @@ pub trait StatelessAead { /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. - fn encrypt( + /// + /// See notes on `Aead::encrypt()` about allowable message payloads and + /// Associated Additional Data (AAD). + fn encrypt<'msg, 'aad>( &self, - additional_data: &[u8], nonce: &GenericArray, - plaintext: &[u8] + plaintext: impl Into>, ) -> Result, Error>; /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. - fn decrypt( + /// + /// See notes on `Aead::encrypt()` and `Aead::decrypt()` about allowable + /// message payloads and Associated Additional Data (AAD). + fn decrypt<'msg, 'aad>( &self, - additional_data: &[u8], nonce: &GenericArray, - ciphertext: &[u8] + ciphertext: impl Into>, ) -> Result, Error>; } @@ -91,23 +119,44 @@ impl Aead for Algo { /// Encrypt the given plaintext slice, and return the resulting ciphertext /// as a vector of bytes. - fn encrypt( + fn encrypt<'msg, 'aad>( &mut self, - additional_data: &[u8], nonce: &GenericArray, - plaintext: &[u8] + plaintext: impl Into>, ) -> Result, Error> { - ::encrypt(self, additional_data, nonce, plaintext) + ::encrypt(self, nonce, plaintext) } /// Decrypt the given ciphertext slice, and return the resulting plaintext /// as a vector of bytes. - fn decrypt( + fn decrypt<'msg, 'aad>( &mut self, - additional_data: &[u8], nonce: &GenericArray, - ciphertext: &[u8] + ciphertext: impl Into>, ) -> Result, Error> { - ::decrypt(self, additional_data, nonce, ciphertext) + ::decrypt(self, nonce, ciphertext) + } +} + +/// AEAD payloads are a combination of a message (plaintext or ciphertext) +/// and "additional associated data" (AAD) to be authenticated (in cleartext) +/// along with the message. +/// +/// If you don't care about AAD, you can pass a `&[u8]` as the payload to +/// `encrypt`/`decrypt` and it will automatically be coerced to this type. +pub struct Payload<'msg, 'aad> { + /// Message to be encrypted/decrypted + pub msg: &'msg [u8], + + /// Optional "additional associated data" to authenticate along with + /// this message. If AAD is provided at the time the message is encrypted, + /// the same AAD *MUST* be provided at the time the message is decrypted, + /// or decryption will fail. + pub aad: &'aad [u8], +} + +impl<'msg, 'aad> From<&'msg [u8]> for Payload<'msg, 'aad> { + fn from(msg: &'msg [u8]) -> Self { + Self { msg, aad: b"" } } }