dryoc/classic/
crypto_kdf.rs1use crate::blake2b;
28use crate::constants::{
29 CRYPTO_GENERICHASH_BLAKE2B_PERSONALBYTES, CRYPTO_GENERICHASH_BLAKE2B_SALTBYTES,
30 CRYPTO_KDF_BLAKE2B_BYTES_MAX, CRYPTO_KDF_BLAKE2B_BYTES_MIN, CRYPTO_KDF_CONTEXTBYTES,
31 CRYPTO_KDF_KEYBYTES,
32};
33use crate::error::Error;
34
35pub type Key = [u8; CRYPTO_KDF_KEYBYTES];
37pub type Context = [u8; CRYPTO_KDF_CONTEXTBYTES];
39
40pub fn crypto_kdf_keygen() -> Key {
43 use crate::rng::copy_randombytes;
44 let mut key = Key::default();
45 copy_randombytes(&mut key);
46 key
47}
48
49pub fn crypto_kdf_derive_from_key(
53 subkey: &mut [u8],
54 subkey_id: u64,
55 context: &Context,
56 main_key: &Key,
57) -> Result<(), Error> {
58 if subkey.len() < CRYPTO_KDF_BLAKE2B_BYTES_MIN || subkey.len() > CRYPTO_KDF_BLAKE2B_BYTES_MAX {
59 Err(dryoc_error!(format!(
60 "invalid subkey length {}, should be at least {} and no more than {}",
61 subkey.len(),
62 CRYPTO_KDF_BLAKE2B_BYTES_MIN,
63 CRYPTO_KDF_BLAKE2B_BYTES_MAX
64 )))
65 } else {
66 let mut ctx_padded = [0u8; CRYPTO_GENERICHASH_BLAKE2B_PERSONALBYTES];
67 let mut salt = [0u8; CRYPTO_GENERICHASH_BLAKE2B_SALTBYTES];
68
69 ctx_padded[..CRYPTO_KDF_CONTEXTBYTES].copy_from_slice(context);
70 salt[..8].copy_from_slice(&subkey_id.to_le_bytes());
71
72 let state = blake2b::State::init(
73 CRYPTO_KDF_KEYBYTES as u8,
74 Some(main_key),
75 Some(&salt),
76 Some(&ctx_padded),
77 )?;
78 state.finalize(subkey)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_derive_key() {
88 use sodiumoxide::crypto::{kdf, secretbox};
89 let main_key = crypto_kdf_keygen();
90 let context = b"hello123";
91
92 for i in 0..20 {
93 let mut key = Key::default();
94 crypto_kdf_derive_from_key(&mut key, i, context, &main_key).expect("kdf failed");
95
96 let mut so_key = secretbox::Key([0; secretbox::KEYBYTES]);
97 kdf::derive_from_key(
98 &mut so_key.0[..],
99 i,
100 *context,
101 &kdf::blake2b::Key::from_slice(&main_key).expect("key failed"),
102 )
103 .expect("so kdf failed");
104
105 assert_eq!(so_key.0, key);
106 }
107 }
108}