Skip to content

Instantly share code, notes, and snippets.

@jess-sol
Created April 10, 2024 17:36
Show Gist options
  • Select an option

  • Save jess-sol/1af6ad8eb348e2be40fb5727115a7cb4 to your computer and use it in GitHub Desktop.

Select an option

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
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