use crate::domain::value_objects::{EdDSAKey, NullifierKey, ViewingKey};
pub trait KeyDeriver {
fn derive_viewing(&self, spending_key: &[u8; 32]) -> ViewingKey;
fn derive_nullifier(&self, spending_key: &[u8; 32]) -> NullifierKey;
fn derive_eddsa(&self, spending_key: &[u8; 32]) -> EdDSAKey;
fn derive_encryption_key(&self, viewing_key: &[u8; 32], commitment: &[u8; 32]) -> [u8; 32];
}
#[cfg(test)]
mod tests {
use super::*;
use crate::domain::value_objects::{EdDSAKey, NullifierKey, ViewingKey};
struct MockDeriver;
impl KeyDeriver for MockDeriver {
fn derive_viewing(&self, k: &[u8; 32]) -> ViewingKey {
ViewingKey(*k)
}
fn derive_nullifier(&self, k: &[u8; 32]) -> NullifierKey {
NullifierKey(*k)
}
fn derive_eddsa(&self, k: &[u8; 32]) -> EdDSAKey {
EdDSAKey(*k)
}
fn derive_encryption_key(&self, vk: &[u8; 32], c: &[u8; 32]) -> [u8; 32] {
let mut r = [0u8; 32];
for i in 0..32 {
r[i] = vk[i] ^ c[i];
}
r
}
}
const SK: [u8; 32] = [42u8; 32];
#[test]
fn test_derive_viewing_returns_viewing_key() {
assert_eq!(MockDeriver.derive_viewing(&SK).0, SK);
}
#[test]
fn test_derive_nullifier_returns_nullifier_key() {
assert_eq!(MockDeriver.derive_nullifier(&SK).0, SK);
}
#[test]
fn test_derive_eddsa_returns_eddsa_key() {
assert_eq!(MockDeriver.derive_eddsa(&SK).0, SK);
}
#[test]
fn test_derive_encryption_key_xor() {
let vk = [0x0Fu8; 32];
let com = [0xF0u8; 32];
let result = MockDeriver.derive_encryption_key(&vk, &com);
assert_eq!(result, [0xFFu8; 32]); }
#[test]
fn test_derive_encryption_key_zero_commitment() {
let vk = [7u8; 32];
assert_eq!(MockDeriver.derive_encryption_key(&vk, &[0u8; 32]), vk);
}
#[test]
fn test_all_keys_derived_from_same_spending_key() {
let vk = MockDeriver.derive_viewing(&SK);
let nk = MockDeriver.derive_nullifier(&SK);
let ek = MockDeriver.derive_eddsa(&SK);
assert_eq!(vk.0, SK);
assert_eq!(nk.0, SK);
assert_eq!(ek.0, SK);
}
}