use crate::IdentityError;
use core::fmt::{Display, Formatter};
use ockam_core::Result;
pub const AES_GCM_NONCE_LEN: usize = 12;
pub const NOISE_NONCE_LEN: usize = 8;
pub const MAX_NONCE: Nonce = Nonce { value: u64::MAX };
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Copy)]
pub struct Nonce {
value: u64,
}
impl Display for Nonce {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.value)
}
}
impl From<u64> for Nonce {
fn from(value: u64) -> Self {
Self { value }
}
}
impl From<Nonce> for u64 {
fn from(value: Nonce) -> Self {
value.value
}
}
impl Nonce {
pub fn new(value: u64) -> Self {
Self { value }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn increment(&mut self) -> Result<()> {
if self == &MAX_NONCE {
return Err(IdentityError::NonceOverflow)?;
}
self.value += 1;
Ok(())
}
pub fn to_aes_gcm_nonce(&self) -> [u8; AES_GCM_NONCE_LEN] {
let mut n: [u8; AES_GCM_NONCE_LEN] = [0; AES_GCM_NONCE_LEN];
n[AES_GCM_NONCE_LEN - NOISE_NONCE_LEN..].copy_from_slice(&self.to_noise_nonce());
n
}
pub fn to_noise_nonce(&self) -> [u8; NOISE_NONCE_LEN] {
self.value.to_be_bytes()
}
}
impl From<[u8; NOISE_NONCE_LEN]> for Nonce {
fn from(value: [u8; NOISE_NONCE_LEN]) -> Self {
let value = u64::from_be_bytes(value);
Self { value }
}
}
impl TryFrom<&[u8]> for Nonce {
type Error = IdentityError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let bytes: [u8; NOISE_NONCE_LEN] =
value.try_into().map_err(|_| IdentityError::InvalidNonce)?;
Ok(bytes.into())
}
}