From 7fc675e8a5913bb1f74f99c076413c2bd104c10c Mon Sep 17 00:00:00 2001 From: Christiaan <31404228+Christiaan676@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:39:12 +0200 Subject: [PATCH] Add AES SIV examples (#533) This adds, AES-SIV examples and most importantly extra documentation that mentions the Rogway paper. The interface of the SIV module is based on this paper, and offers a more detail description of wat all the parameters are intended for. --- aes-siv/src/lib.rs | 1 + aes-siv/src/siv.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/aes-siv/src/lib.rs b/aes-siv/src/lib.rs index f9fcd020..40752006 100644 --- a/aes-siv/src/lib.rs +++ b/aes-siv/src/lib.rs @@ -115,6 +115,7 @@ pub type Tag = Array; /// The `SivAead` type wraps the more powerful `Siv` interface in a more /// commonly used Authenticated Encryption with Associated Data (AEAD) API, /// which accepts a key, nonce, and associated data when encrypting/decrypting. +/// See the [`Siv`](mod@siv) module documentation for more information and examples. pub struct SivAead where Self: KeySizeUser, diff --git a/aes-siv/src/siv.rs b/aes-siv/src/siv.rs index b7c00d69..be754ff0 100644 --- a/aes-siv/src/siv.rs +++ b/aes-siv/src/siv.rs @@ -1,7 +1,72 @@ //! The Synthetic Initialization Vector (SIV) misuse-resistant block cipher -//! mode of operation ([RFC 5297][1]). +//! mode of operation ([RFC 5297][1]). The interface is based on the [Rogaway paper][2]. //! +//! # Deterministic Authenticated Encryption Example +//! Deterministic encryption with additional data. Suitable for example for key wrapping. +//! Based on the test vector in [RFC 5297 Appendix: A1][3] +#![cfg_attr(feature = "std", doc = "```")] +#![cfg_attr(not(feature = "std"), doc = "```ignore")] +//! # fn main() -> Result<(), Box> { +//! use aes_siv::{siv::Aes128Siv, KeyInit}; +//! use hex_literal::hex; +//! +//! let key = hex!("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); +//! let ad = hex!("101112131415161718191a1b1c1d1e1f2021222324252627"); +//! let plain_text = hex!("112233445566778899aabbccddee"); +//! +//! let header = [&ad]; +//! let encrypt = Aes128Siv::new(&key.into()) +//! .encrypt(&header, &plain_text)?; +//! +//! assert_eq!( +//! hex!("85632d07c6e8f37f950acd320a2ecc9340c02b9690c4dc04daef7f6afe5c").to_vec(), +//! encrypt +//! ); +//! let decrypted = Aes128Siv::new(&key.into()) +//! .decrypt(&header, &encrypt)?; +//! +//! assert_eq!(plain_text.to_vec(), decrypted); +//! # Ok(()) +//! # } +//! ``` +//! +//! # Nonce-Based Authenticated Encryption Example +//! Nonce-based encryption with multiple additional data vectors. +//! Based on the test vector in [RFC 5297 Appendix: A2][4] +#![cfg_attr(feature = "std", doc = "```")] +#![cfg_attr(not(feature = "std"), doc = "```ignore")] +//! # fn main() -> Result<(), Box> { +//! use aes_siv::{siv::Aes128Siv, KeyInit}; +//! use hex_literal::hex; +//! +//! let key = hex!("7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f"); +//! let ad1 = hex!("00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100"); +//! let ad2 = hex!("102030405060708090a0"); +//! // Note that for production the nonce should be generated by for example: Aes256SivAead::generate_nonce +//! let nonce = hex!("09f911029d74e35bd84156c5635688c0"); +//! +//! let plain_text = hex!("7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553"); +//! +//! let header: [&[u8]; 3] = [&ad1, &ad2, &nonce]; +//! let encrypt = Aes128Siv::new(&key.into()) +//! .encrypt(&header, &plain_text)?; +//! +//! assert_eq!( +//! hex!("7bdb6e3b432667eb06f4d14bff2fbd0fcb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d").to_vec(), +//! encrypt +//! ); +//! +//! let decrypted = Aes128Siv::new(&key.into()) +//! .decrypt(&header, &encrypt)?; +//! +//! assert_eq!(plain_text.to_vec(), decrypted); +//! # Ok(()) +//! # } +//! ``` //! [1]: https://tools.ietf.org/html/rfc5297 +//! [2]: https://web.cs.ucdavis.edu/~rogaway/papers/siv.pdf +//! [3]: https://datatracker.ietf.org/doc/html/rfc5297#appendix-A.1 +//! [4]: https://datatracker.ietf.org/doc/html/rfc5297#appendix-A.2 use crate::Tag; use aead::{ @@ -174,7 +239,8 @@ where Ok(siv_tag) } - /// Decrypt the given ciphertext, allocating and returning a Vec for the plaintext + /// Decrypt the given ciphertext, allocating and returning a `Vec` for the plaintext. + /// Or returning an error in the event the provided authentication tag does not match the given ciphertext. #[cfg(feature = "alloc")] pub fn decrypt(&mut self, headers: I, ciphertext: &[u8]) -> Result, Error> where