Skip to content

aead: Add Payload type #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 72 additions & 23 deletions aead/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -33,22 +33,46 @@ pub trait Aead {
/// ciphertext vs. a plaintext.
type CiphertextOverhead: ArrayLength<u8> + 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<u8, Self::NonceSize>,
plaintext: &[u8]
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, 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<u8, Self::NonceSize>,
ciphertext: &[u8]
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error>;
}

Expand All @@ -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<u8, Self::NonceSize>,
plaintext: &[u8]
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, 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<u8, Self::NonceSize>,
ciphertext: &[u8]
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error>;
}

Expand All @@ -91,23 +119,44 @@ impl<Algo: StatelessAead> 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<u8, Self::NonceSize>,
plaintext: &[u8]
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
<Self as StatelessAead>::encrypt(self, additional_data, nonce, plaintext)
<Self as StatelessAead>::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<u8, Self::NonceSize>,
ciphertext: &[u8]
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
<Self as StatelessAead>::decrypt(self, additional_data, nonce, ciphertext)
<Self as StatelessAead>::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"" }
}
}