Created
April 10, 2024 17:36
-
-
Save jess-sol/1af6ad8eb348e2be40fb5727115a7cb4 to your computer and use it in GitHub Desktop.
Example of a Ring counting NonceSequence. Counter uses 11 bytes so the last byte can be used to identify the last chunk (STREAM construct) - https://github.com/C2SP/C2SP/blob/main/age.md#payload
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::mem::size_of; | |
| use ring::aead::{self, Nonce, NonceSequence}; | |
| /// The u128 is treated as an 11 byte counter, and will panic on overflow | |
| const COUNTER_BYTES: usize = 11; | |
| const COUNTER_MAX_SIZE: u128 = 1 << (8 * COUNTER_BYTES); | |
| pub(crate) struct CounterNonceSequence(u128); | |
| impl NonceSequence for CounterNonceSequence { | |
| fn advance(&mut self) -> Result<aead::Nonce, ring::error::Unspecified> { | |
| let old_nonce = self.0; | |
| self.0 += 1; | |
| // Ensure we don't "overflow" past 11 bytes | |
| assert!(self.0 < COUNTER_MAX_SIZE); | |
| let mut nonce: [u8; 12] = [0u8; 12]; | |
| nonce[..COUNTER_BYTES] | |
| .copy_from_slice(&old_nonce.to_be_bytes()[(size_of::<u128>() - COUNTER_BYTES)..]); | |
| Ok(Nonce::assume_unique_for_key(nonce)) | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use ring::aead::NonceSequence; | |
| use super::CounterNonceSequence; | |
| #[test] | |
| fn validate_works() { | |
| let mut nonce = CounterNonceSequence(0); | |
| assert_eq!(&[0u8; 12], nonce.advance().unwrap().as_ref()); | |
| } | |
| #[test] | |
| #[should_panic] | |
| fn validate_overflow() { | |
| let mut nonce = CounterNonceSequence(!0u128 >> (8 * 5)); | |
| nonce.advance().unwrap(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment