From 9e3cfc2fd6da871526ebfd586a6200b7e0e95a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= Date: Sat, 9 Mar 2024 11:49:40 +0100 Subject: [PATCH] Use the time period instead of the timestamp --- src/encryption.rs | 21 +++++++++++---------- src/kdf.rs | 20 +++++++++++++------- src/storage.rs | 32 ++++++++++++++++---------------- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/encryption.rs b/src/encryption.rs index 99e7257..e2e9ede 100644 --- a/src/encryption.rs +++ b/src/encryption.rs @@ -17,9 +17,9 @@ pub(crate) struct EncryptedData { fn generate_aad( key_context: &KeyContext, data_context: &[impl AsRef<[u8]>], - ts: Option, + time_period: Option, ) -> String { - let key_context_canon = canonicalize(&key_context.get_value(ts)); + let key_context_canon = canonicalize(&key_context.get_value(time_period)); let data_context_canon = canonicalize(data_context); join_canonicalized_str(&key_context_canon, &data_context_canon) } @@ -30,17 +30,18 @@ pub fn encrypt( data: impl AsRef<[u8]>, data_context: &[impl AsRef<[u8]>], ) -> Result { - let ts = if key_context.is_periodic() { - Some(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs()) + let tp = if key_context.is_periodic() { + let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); + key_context.get_time_period(ts) } else { None }; let ikm = ikml.get_latest_ikm()?; - let key = derive_key(ikm, key_context, ts); - let aad = generate_aad(key_context, data_context, ts); + let key = derive_key(ikm, key_context, tp); + let aad = generate_aad(key_context, data_context, tp); let encryption_function = ikm.scheme.get_encryption(); let encrypted_data = encryption_function(&key, data.as_ref(), &aad)?; - Ok(storage::encode_cipher(ikm.id, &encrypted_data, ts)) + Ok(storage::encode_cipher(ikm.id, &encrypted_data, tp)) } pub fn decrypt( @@ -49,10 +50,10 @@ pub fn decrypt( stored_data: &str, data_context: &[impl AsRef<[u8]>], ) -> Result> { - let (ikm_id, encrypted_data, ts) = storage::decode_cipher(stored_data)?; + let (ikm_id, encrypted_data, tp) = storage::decode_cipher(stored_data)?; let ikm = ikml.get_ikm_by_id(ikm_id)?; - let key = derive_key(ikm, key_context, ts); - let aad = generate_aad(key_context, data_context, ts); + let key = derive_key(ikm, key_context, tp); + let aad = generate_aad(key_context, data_context, tp); let decryption_function = ikm.scheme.get_decryption(); decryption_function(&key, &encrypted_data, &aad) } diff --git a/src/kdf.rs b/src/kdf.rs index 5f47d52..f5f92a6 100644 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -9,16 +9,18 @@ pub struct KeyContext { } impl KeyContext { - pub(crate) fn get_value(&self, ts: Option) -> Vec> { + pub(crate) fn get_value(&self, time_period: Option) -> Vec> { let mut ret: Vec> = self.ctx.iter().map(|s| s.as_bytes().to_vec()).collect(); - if let Some(p) = self.periodicity { - let ts = ts.unwrap_or(0); - let c = ts % p; - ret.push(c.to_le_bytes().to_vec()); + if let Some(tp) = time_period { + ret.push(tp.to_le_bytes().to_vec()); } ret } + pub(crate) fn get_time_period(&self, timestamp: u64) -> Option { + self.periodicity.map(|p| timestamp / p) + } + pub(crate) fn is_periodic(&self) -> bool { self.periodicity.is_some() } @@ -33,8 +35,12 @@ impl From<[&str; N]> for KeyContext { } } -pub(crate) fn derive_key(ikm: &InputKeyMaterial, ctx: &KeyContext, ts: Option) -> Vec { - let key_context = canonicalize(&ctx.get_value(ts)); +pub(crate) fn derive_key( + ikm: &InputKeyMaterial, + ctx: &KeyContext, + time_period: Option, +) -> Vec { + let key_context = canonicalize(&ctx.get_value(time_period)); let kdf = ikm.scheme.get_kdf(); kdf(&key_context, &ikm.content) } diff --git a/src/storage.rs b/src/storage.rs index 7398394..1e6d90e 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -32,7 +32,7 @@ pub(crate) fn encode_ikm_list(ikml: &InputKeyMaterialList) -> Result { pub(crate) fn encode_cipher( ikm_id: IkmId, encrypted_data: &EncryptedData, - ts: Option, + time_period: Option, ) -> String { let mut ret = String::new(); ret += &encode_data(&ikm_id.to_le_bytes()); @@ -40,9 +40,9 @@ pub(crate) fn encode_cipher( ret += &encode_data(&encrypted_data.nonce); ret += STORAGE_SEPARATOR; ret += &encode_data(&encrypted_data.ciphertext); - if let Some(ts) = ts { + if let Some(time_period) = time_period { ret += STORAGE_SEPARATOR; - ret += &encode_data(&ts.to_le_bytes()); + ret += &encode_data(&time_period.to_le_bytes()); } ret } @@ -68,15 +68,15 @@ pub(crate) fn decode_ikm_list(data: &str) -> Result { pub(crate) fn decode_cipher(data: &str) -> Result<(IkmId, EncryptedData, Option)> { let mut v: Vec<&str> = data.split(STORAGE_SEPARATOR).collect(); - let ts = if v.len() == NB_PARTS + 1 { + let time_period = if v.len() == NB_PARTS + 1 { match v.pop() { - Some(ts_raw) => { - let ts_raw = decode_data(ts_raw)?; - let ts_raw: [u8; 8] = ts_raw + Some(tp_raw) => { + let tp_raw = decode_data(tp_raw)?; + let tp_raw: [u8; 8] = tp_raw .clone() .try_into() - .map_err(|_| Error::ParsingEncodedDataInvalidTimestamp(ts_raw))?; - Some(u64::from_le_bytes(ts_raw)) + .map_err(|_| Error::ParsingEncodedDataInvalidTimestamp(tp_raw))?; + Some(u64::from_le_bytes(tp_raw)) } None => None, } @@ -96,7 +96,7 @@ pub(crate) fn decode_cipher(data: &str) -> Result<(IkmId, EncryptedData, Option< nonce: decode_data(v[1])?, ciphertext: decode_data(v[2])?, }; - Ok((id, encrypted_data, ts)) + Ok((id, encrypted_data, time_period)) } #[cfg(test)] @@ -130,11 +130,11 @@ mod tests { fn decode() { let res = super::decode_cipher(TEST_STR); assert!(res.is_ok(), "res: {res:?}"); - let (id, data, ts) = res.unwrap(); + let (id, data, tp) = res.unwrap(); assert_eq!(id, TEST_IKM_ID); assert_eq!(data.nonce, TEST_NONCE); assert_eq!(data.ciphertext, TEST_CIPHERTEXT); - assert_eq!(ts, None); + assert_eq!(tp, None); } #[test] @@ -144,17 +144,17 @@ mod tests { ciphertext: TEST_CIPHERTEXT.into(), }; let s = super::encode_cipher(TEST_IKM_ID, &data, None); - let (id, decoded_data, ts) = super::decode_cipher(&s).unwrap(); + let (id, decoded_data, tp) = super::decode_cipher(&s).unwrap(); assert_eq!(id, TEST_IKM_ID); assert_eq!(decoded_data.nonce, data.nonce); assert_eq!(decoded_data.ciphertext, data.ciphertext); - assert_eq!(ts, None); + assert_eq!(tp, None); } #[test] fn decode_encode() { - let (id, data, ts) = super::decode_cipher(TEST_STR).unwrap(); - let s = super::encode_cipher(id, &data, ts); + let (id, data, tp) = super::decode_cipher(TEST_STR).unwrap(); + let s = super::encode_cipher(id, &data, tp); assert_eq!(&s, TEST_STR); } }