diff --git a/src/canonicalization.rs b/src/canonicalization.rs new file mode 100644 index 0000000..01c4649 --- /dev/null +++ b/src/canonicalization.rs @@ -0,0 +1,44 @@ +use base64ct::{Base64UrlUnpadded, Encoding}; + +const CANONICALIZATION_BUFFER_SIZE: usize = 1024; +const CANONICALIZATION_SEPARATOR: &str = ":"; + +pub(crate) fn canonicalize(key_context: &[&str]) -> String { + match key_context.len() { + 0 => String::new(), + 1 => key_context[0].to_string(), + _ => { + let mut ret = String::with_capacity(CANONICALIZATION_BUFFER_SIZE); + for (i, ctx_elem) in key_context.iter().enumerate() { + if i != 0 { + ret += CANONICALIZATION_SEPARATOR; + } + ret += &Base64UrlUnpadded::encode_string(ctx_elem.as_bytes()); + } + ret + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn canonicalize_empty() { + let canon = canonicalize(&[]); + assert_eq!(canon, String::new()); + } + + #[test] + fn canonicalize_one() { + let canon = canonicalize(&["test"]); + assert_eq!(&canon, "test"); + } + + #[test] + fn canonicalize_many() { + let canon = canonicalize(&["test", "bis", "ter", ""]); + assert_eq!(&canon, "dGVzdA:Ymlz:dGVy:"); + } +} diff --git a/src/kdf.rs b/src/kdf.rs index 9d04f93..8dc3079 100644 --- a/src/kdf.rs +++ b/src/kdf.rs @@ -1,28 +1,8 @@ +use crate::canonicalization::canonicalize; use crate::ikm::InputKeyMaterial; -use base64ct::{Base64UrlUnpadded, Encoding}; pub(crate) type KdfFunction = dyn Fn(&str, &[u8]) -> Vec; -const CANONICALIZATION_BUFFER_SIZE: usize = 1024; -const CANONICALIZATION_SEPARATOR: &str = ":"; - -fn canonicalize(key_context: &[&str]) -> String { - match key_context.len() { - 0 => String::new(), - 1 => key_context[0].to_string(), - _ => { - let mut ret = String::with_capacity(CANONICALIZATION_BUFFER_SIZE); - for (i, ctx_elem) in key_context.iter().enumerate() { - if i != 0 { - ret += CANONICALIZATION_SEPARATOR; - } - ret += &Base64UrlUnpadded::encode_string(ctx_elem.as_bytes()); - } - ret - } - } -} - pub(crate) fn derive_key(ikm: &InputKeyMaterial, key_context: &[&str]) -> Vec { let key_context = canonicalize(key_context); let kdf = ikm.scheme.get_kdf(); @@ -32,26 +12,3 @@ pub(crate) fn derive_key(ikm: &InputKeyMaterial, key_context: &[&str]) -> Vec Vec { blake3::derive_key(context, ikm).to_vec() } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn canonicalize_empty() { - let canon = canonicalize(&[]); - assert_eq!(canon, String::new()); - } - - #[test] - fn canonicalize_one() { - let canon = canonicalize(&["test"]); - assert_eq!(&canon, "test"); - } - - #[test] - fn canonicalize_many() { - let canon = canonicalize(&["test", "bis", "ter", ""]); - assert_eq!(&canon, "dGVzdA:Ymlz:dGVy:"); - } -} diff --git a/src/lib.rs b/src/lib.rs index 03a0d8a..1c5cbec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod canonicalization; #[cfg(feature = "encryption")] mod encryption; mod error;