Allow to encrypt at a specific timestamp
This commit is contained in:
parent
fd7dccddea
commit
224171c6d5
3 changed files with 63 additions and 16 deletions
|
@ -15,6 +15,7 @@ categories = ["cryptography"]
|
||||||
default = ["encryption", "ikm-management"]
|
default = ["encryption", "ikm-management"]
|
||||||
encryption = []
|
encryption = []
|
||||||
ikm-management = []
|
ikm-management = []
|
||||||
|
encrypt-at = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aes-gcm = { version = "0.10.3", default-features = false, features = ["std", "aes"] }
|
aes-gcm = { version = "0.10.3", default-features = false, features = ["std", "aes"] }
|
||||||
|
|
|
@ -40,14 +40,35 @@ impl<'a> Coffio<'a> {
|
||||||
key_context: &KeyContext,
|
key_context: &KeyContext,
|
||||||
data_context: &DataContext,
|
data_context: &DataContext,
|
||||||
data: impl AsRef<[u8]>,
|
data: impl AsRef<[u8]>,
|
||||||
|
) -> Result<String> {
|
||||||
|
self.process_encrypt_at(key_context, data_context, data, SystemTime::now())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "encrypt-at")]
|
||||||
|
pub fn encrypt_at(
|
||||||
|
&self,
|
||||||
|
key_context: &KeyContext,
|
||||||
|
data_context: &DataContext,
|
||||||
|
data: impl AsRef<[u8]>,
|
||||||
|
encryption_time: SystemTime,
|
||||||
|
) -> Result<String> {
|
||||||
|
self.process_encrypt_at(key_context, data_context, data, encryption_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_encrypt_at(
|
||||||
|
&self,
|
||||||
|
key_context: &KeyContext,
|
||||||
|
data_context: &DataContext,
|
||||||
|
data: impl AsRef<[u8]>,
|
||||||
|
encryption_time: SystemTime,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let tp = if key_context.is_periodic() {
|
let tp = if key_context.is_periodic() {
|
||||||
let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
|
let ts = encryption_time.duration_since(UNIX_EPOCH)?.as_secs();
|
||||||
key_context.get_time_period(ts)
|
key_context.get_time_period(ts)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let ikm = self.ikm_list.get_latest_ikm()?;
|
let ikm = self.ikm_list.get_latest_ikm(encryption_time)?;
|
||||||
let key = derive_key(ikm, key_context, tp);
|
let key = derive_key(ikm, key_context, tp);
|
||||||
let gen_nonce_function = ikm.scheme.get_gen_nonce();
|
let gen_nonce_function = ikm.scheme.get_gen_nonce();
|
||||||
let nonce = gen_nonce_function()?;
|
let nonce = gen_nonce_function()?;
|
||||||
|
|
53
src/ikm.rs
53
src/ikm.rs
|
@ -238,12 +238,15 @@ impl InputKeyMaterialList {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "encryption"))]
|
#[cfg(any(test, feature = "encryption"))]
|
||||||
pub(crate) fn get_latest_ikm(&self) -> Result<&InputKeyMaterial> {
|
pub(crate) fn get_latest_ikm(&self, encryption_time: SystemTime) -> Result<&InputKeyMaterial> {
|
||||||
let now = SystemTime::now();
|
|
||||||
self.ikm_lst
|
self.ikm_lst
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|&ikm| !ikm.is_revoked && ikm.not_before < now && ikm.not_after > now)
|
.find(|&ikm| {
|
||||||
|
!ikm.is_revoked
|
||||||
|
&& ikm.not_before < encryption_time
|
||||||
|
&& ikm.not_after > encryption_time
|
||||||
|
})
|
||||||
.ok_or(Error::IkmNoneAvailable)
|
.ok_or(Error::IkmNoneAvailable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,15 +477,15 @@ mod ikm_management {
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
|
|
||||||
let latest_ikm = lst.get_latest_ikm().unwrap();
|
let latest_ikm = lst.get_latest_ikm(SystemTime::now()).unwrap();
|
||||||
assert_eq!(latest_ikm.id, 2);
|
assert_eq!(latest_ikm.id, 2);
|
||||||
|
|
||||||
lst.delete_ikm(2);
|
lst.delete_ikm(2);
|
||||||
let latest_ikm = lst.get_latest_ikm().unwrap();
|
let latest_ikm = lst.get_latest_ikm(SystemTime::now()).unwrap();
|
||||||
assert_eq!(latest_ikm.id, 1);
|
assert_eq!(latest_ikm.id, 1);
|
||||||
|
|
||||||
lst.delete_ikm(1);
|
lst.delete_ikm(1);
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::now());
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,15 +495,15 @@ mod ikm_management {
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
|
|
||||||
let latest_ikm = lst.get_latest_ikm().unwrap();
|
let latest_ikm = lst.get_latest_ikm(SystemTime::now()).unwrap();
|
||||||
assert_eq!(latest_ikm.id, 2);
|
assert_eq!(latest_ikm.id, 2);
|
||||||
|
|
||||||
let _ = lst.revoke_ikm(2);
|
let _ = lst.revoke_ikm(2);
|
||||||
let latest_ikm = lst.get_latest_ikm().unwrap();
|
let latest_ikm = lst.get_latest_ikm(SystemTime::now()).unwrap();
|
||||||
assert_eq!(latest_ikm.id, 1);
|
assert_eq!(latest_ikm.id, 1);
|
||||||
|
|
||||||
let _ = lst.revoke_ikm(1);
|
let _ = lst.revoke_ikm(1);
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::now());
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,15 +521,37 @@ mod ikm_management {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_latest_ikm() {
|
fn get_latest_ikm_epoch() {
|
||||||
let res = InputKeyMaterialList::import(TEST_STR);
|
let res = InputKeyMaterialList::import(TEST_STR);
|
||||||
assert!(res.is_ok(), "res: {res:?}");
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
let lst = res.unwrap();
|
let lst = res.unwrap();
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::UNIX_EPOCH);
|
||||||
|
assert_eq!(res.err(), Some(Error::IkmNoneAvailable))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_latest_ikm_1_712_475_802() {
|
||||||
|
let ts = SystemTime::UNIX_EPOCH + Duration::from_secs(1_712_475_802);
|
||||||
|
let res = InputKeyMaterialList::import(TEST_STR);
|
||||||
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
|
let lst = res.unwrap();
|
||||||
|
let res = lst.get_latest_ikm(ts);
|
||||||
assert!(res.is_ok(), "res: {res:?}");
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
let ikm = res.unwrap();
|
let ikm = res.unwrap();
|
||||||
assert_eq!(ikm.id, 3);
|
assert_eq!(ikm.id, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_latest_ikm_1_592_734_902() {
|
||||||
|
let ts = SystemTime::UNIX_EPOCH + Duration::from_secs(1_592_734_902);
|
||||||
|
let res = InputKeyMaterialList::import(TEST_STR);
|
||||||
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
|
let lst = res.unwrap();
|
||||||
|
let res = lst.get_latest_ikm(ts);
|
||||||
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
|
let ikm = res.unwrap();
|
||||||
|
assert_eq!(ikm.id, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "encryption", feature = "ikm-management"))]
|
#[cfg(all(test, feature = "encryption", feature = "ikm-management"))]
|
||||||
|
@ -540,7 +565,7 @@ mod encryption {
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
let (not_before, not_after) = get_default_time_period();
|
let (not_before, not_after) = get_default_time_period();
|
||||||
let _ = lst.add_custom_ikm(Scheme::XChaCha20Poly1305WithBlake3, not_before, not_after);
|
let _ = lst.add_custom_ikm(Scheme::XChaCha20Poly1305WithBlake3, not_before, not_after);
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::now());
|
||||||
assert!(res.is_ok(), "res: {res:?}");
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
let latest_ikm = res.unwrap();
|
let latest_ikm = res.unwrap();
|
||||||
assert_eq!(latest_ikm.id, 3);
|
assert_eq!(latest_ikm.id, 3);
|
||||||
|
@ -555,7 +580,7 @@ mod encryption {
|
||||||
let _ = lst.add_ikm();
|
let _ = lst.add_ikm();
|
||||||
let (not_before, not_after) = get_default_time_period();
|
let (not_before, not_after) = get_default_time_period();
|
||||||
let _ = lst.add_custom_ikm(Scheme::Aes128GcmWithSha256, not_before, not_after);
|
let _ = lst.add_custom_ikm(Scheme::Aes128GcmWithSha256, not_before, not_after);
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::now());
|
||||||
assert!(res.is_ok(), "res: {res:?}");
|
assert!(res.is_ok(), "res: {res:?}");
|
||||||
let latest_ikm = res.unwrap();
|
let latest_ikm = res.unwrap();
|
||||||
assert_eq!(latest_ikm.id, 3);
|
assert_eq!(latest_ikm.id, 3);
|
||||||
|
@ -566,7 +591,7 @@ mod encryption {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_latest_ikm_empty() {
|
fn get_latest_ikm_empty() {
|
||||||
let lst = InputKeyMaterialList::new();
|
let lst = InputKeyMaterialList::new();
|
||||||
let res = lst.get_latest_ikm();
|
let res = lst.get_latest_ikm(SystemTime::now());
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue