Add a cryptographic scheme to the IKM

This commit is contained in:
Rodolphe Bréard 2024-02-15 10:00:06 +01:00
parent dcefc43efd
commit 32eba4345f
3 changed files with 36 additions and 9 deletions

View file

@ -1,12 +1,14 @@
use crate::Scheme;
use base64ct::{Base64UrlUnpadded, Encoding}; use base64ct::{Base64UrlUnpadded, Encoding};
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
const IKM_STRUCT_SIZE: usize = 53; const IKM_STRUCT_SIZE: usize = 57;
const IKM_CONTENT_SIZE: usize = 32; const IKM_CONTENT_SIZE: usize = 32;
#[derive(Debug)] #[derive(Debug)]
pub struct InputKeyMaterial { pub struct InputKeyMaterial {
id: u32, id: u32,
scheme: Scheme,
content: [u8; IKM_CONTENT_SIZE], content: [u8; IKM_CONTENT_SIZE],
created_at: SystemTime, created_at: SystemTime,
expire_at: SystemTime, expire_at: SystemTime,
@ -17,6 +19,7 @@ impl InputKeyMaterial {
fn as_bytes(&self) -> [u8; IKM_STRUCT_SIZE] { fn as_bytes(&self) -> [u8; IKM_STRUCT_SIZE] {
let mut res = Vec::with_capacity(IKM_STRUCT_SIZE); let mut res = Vec::with_capacity(IKM_STRUCT_SIZE);
res.extend_from_slice(&self.id.to_le_bytes()); res.extend_from_slice(&self.id.to_le_bytes());
res.extend_from_slice(&(self.scheme as u32).to_le_bytes());
res.extend_from_slice(&self.content); res.extend_from_slice(&self.content);
res.extend_from_slice( res.extend_from_slice(
&self &self
@ -41,18 +44,21 @@ impl InputKeyMaterial {
fn from_bytes(b: [u8; IKM_STRUCT_SIZE]) -> Self { fn from_bytes(b: [u8; IKM_STRUCT_SIZE]) -> Self {
Self { Self {
id: u32::from_le_bytes(b[0..4].try_into().unwrap()), id: u32::from_le_bytes(b[0..4].try_into().unwrap()),
content: b[4..36].try_into().unwrap(), scheme: u32::from_le_bytes(b[4..8].try_into().unwrap())
.try_into()
.unwrap(),
content: b[8..40].try_into().unwrap(),
created_at: SystemTime::UNIX_EPOCH created_at: SystemTime::UNIX_EPOCH
.checked_add(Duration::from_secs(u64::from_le_bytes( .checked_add(Duration::from_secs(u64::from_le_bytes(
b[36..44].try_into().unwrap(), b[40..48].try_into().unwrap(),
))) )))
.unwrap(), .unwrap(),
expire_at: SystemTime::UNIX_EPOCH expire_at: SystemTime::UNIX_EPOCH
.checked_add(Duration::from_secs(u64::from_le_bytes( .checked_add(Duration::from_secs(u64::from_le_bytes(
b[44..52].try_into().unwrap(), b[48..56].try_into().unwrap(),
))) )))
.unwrap(), .unwrap(),
is_revoked: b[52] != 0, is_revoked: b[56] != 0,
} }
} }
} }
@ -79,6 +85,7 @@ impl InputKeyMaterialList {
self.id_counter += 1; self.id_counter += 1;
self.ikm_lst.push(InputKeyMaterial { self.ikm_lst.push(InputKeyMaterial {
id: self.id_counter, id: self.id_counter,
scheme: crate::DEFAULT_SCHEME,
created_at, created_at,
expire_at: created_at + duration, expire_at: created_at + duration,
is_revoked: false, is_revoked: false,
@ -166,12 +173,13 @@ mod tests {
let _ = lst.add_ikm(); let _ = lst.add_ikm();
let s = lst.export(); let s = lst.export();
assert_eq!(s.len(), 76); assert_eq!(s.len(), 82);
} }
#[test] #[test]
fn import() { fn import() {
let s = "AQAAAAEAAABucjrrlDwu3T9cIYqsmOg_h6_xO77fia0bahsIYnx9G9QVzWUAAAAAVEmuZwAAAAAA"; let s =
"AQAAAAEAAAABAAAANGFtbdYEN0s7dzCfMm7dYeQWD64GdmuKsYSiKwppAhmkz81lAAAAACQDr2cAAAAAAA";
let res = InputKeyMaterialList::import(s); let res = InputKeyMaterialList::import(s);
assert!(res.is_ok()); assert!(res.is_ok());
let lst = res.unwrap(); let lst = res.unwrap();
@ -179,11 +187,12 @@ mod tests {
assert_eq!(lst.ikm_lst.len(), 1); assert_eq!(lst.ikm_lst.len(), 1);
let ikm = lst.ikm_lst.first().unwrap(); let ikm = lst.ikm_lst.first().unwrap();
assert_eq!(ikm.id, 1); assert_eq!(ikm.id, 1);
assert_eq!(ikm.scheme, Scheme::XChaCha20Poly1305WithBlake3);
assert_eq!( assert_eq!(
ikm.content, ikm.content,
[ [
110, 114, 58, 235, 148, 60, 46, 221, 63, 92, 33, 138, 172, 152, 232, 63, 135, 175, 52, 97, 109, 109, 214, 4, 55, 75, 59, 119, 48, 159, 50, 110, 221, 97, 228, 22, 15,
241, 59, 190, 223, 137, 173, 27, 106, 27, 8, 98, 124, 125, 27 174, 6, 118, 107, 138, 177, 132, 162, 43, 10, 105, 2, 25
] ]
); );
assert_eq!(ikm.is_revoked, false); assert_eq!(ikm.is_revoked, false);

View file

@ -1,5 +1,8 @@
mod ikm; mod ikm;
mod scheme;
pub use ikm::InputKeyMaterialList; pub use ikm::InputKeyMaterialList;
pub use scheme::Scheme;
const DEFAULT_IKM_DURATION: u64 = 60 * 60 * 24 * 365; // In seconds const DEFAULT_IKM_DURATION: u64 = 60 * 60 * 24 * 365; // In seconds
const DEFAULT_SCHEME: Scheme = Scheme::XChaCha20Poly1305WithBlake3;

15
src/scheme.rs Normal file
View file

@ -0,0 +1,15 @@
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Scheme {
XChaCha20Poly1305WithBlake3 = 1,
}
impl TryFrom<u32> for Scheme {
type Error = &'static str;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(Scheme::XChaCha20Poly1305WithBlake3),
_ => Err("unknown scheme"),
}
}
}