caead 0.0.1

Committing AEAD constructions from existing AEADs.
Documentation
#![no_std]

//! Committing AEAD constructions. Allows one to construct key/fully committing AEAD constructions
//! from [existing AEADs].
//!
//! [existing AEADS]: aead

use core::marker::PhantomData;

use aead::generic_array::GenericArray;
use aead::{AeadCore, AeadInPlace, Error, KeyInit, KeySizeUser, Nonce, Tag};
use digest::Digest;

/// CTX key committing AEAD construction from [“On Committing Authenticated Encryption” by John Chan and Phillip Rogaway](https://eprint.iacr.org/2022/1260).
pub struct CtxCommitment<A, H>
where
    A: AeadCore + KeyInit,
    H: Digest,
{
    key: GenericArray<u8, A::KeySize>,
    naead: A,
    _digest: PhantomData<H>,
}

impl<A, H> AeadCore for CtxCommitment<A, H>
where
    A: AeadCore + KeyInit,
    H: Digest,
{
    type NonceSize = A::NonceSize;
    type TagSize = H::OutputSize;
    type CiphertextOverhead = A::CiphertextOverhead;
}

impl<A, H> KeySizeUser for CtxCommitment<A, H>
where
    A: AeadCore + KeyInit,
    H: Digest,
{
    type KeySize = A::KeySize;
}

impl<A, H> KeyInit for CtxCommitment<A, H>
where
    A: AeadCore + KeyInit,
    H: Digest,
{
    fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
        Self {
            key: key.clone(),
            naead: A::new(key),
            _digest: PhantomData,
        }
    }
}

impl<A, H> CtxCommitment<A, H>
where
    A: AeadCore + KeyInit + AeadInPlace,
    H: Digest,
{
    /// Currently not in [`AeadInPlace`] due to the inability to decrypt without verifying
    /// the tag.
    pub fn encrypt_in_place_detached(
        &self,
        nonce: &Nonce<Self>,
        associated_data: &[u8],
        buffer: &mut [u8],
    ) -> Result<Tag<Self>, Error> {
        let mut tag = Tag::<Self>::default();

        let ntag = self
            .naead
            .encrypt_in_place_detached(nonce, associated_data, buffer)?;

        H::new()
            .chain_update(&self.key)
            .chain_update(nonce)
            .chain_update(associated_data)
            .chain_update(ntag)
            .finalize_into(&mut tag);

        Ok(tag)
    }
}