hopr_crypto_sphinx/
derivation.rs1use hopr_crypto_types::prelude::*;
2
3const HASH_KEY_PACKET_TAG: &str = "HASH_KEY_PACKET_TAG";
5
6pub(crate) fn create_kdf_instance<S: AsRef<[u8]>>(
7 secret: &S,
8 context: &str,
9 salt: Option<&[u8]>,
10) -> hopr_crypto_types::errors::Result<Blake3Output> {
11 let key_material = secret.as_ref();
12 if key_material.len() < 16 {
13 return Err(CryptoError::InvalidInputValue("secret must have at least 128-bits"));
14 }
15
16 if let Some(salt) = salt {
17 Ok(Blake3::new_derive_key(context)
18 .update_reader(salt)
19 .map_err(|_| CryptoError::InvalidInputValue("salt"))?
20 .update_reader(key_material)
21 .map_err(|_| CryptoError::InvalidInputValue("key"))?
22 .finalize_xof())
23 } else {
24 Ok(Blake3::new_derive_key(context)
25 .update_reader(key_material)
26 .map_err(|_| CryptoError::InvalidInputValue("key"))?
27 .finalize_xof())
28 }
29}
30
31pub fn derive_packet_tag(secret: &SecretKey) -> hopr_crypto_types::errors::Result<PacketTag> {
33 let mut packet_tag: PacketTag = [0u8; PACKET_TAG_LENGTH];
34
35 let mut output = create_kdf_instance(secret, HASH_KEY_PACKET_TAG, None)?;
36 output.fill(&mut packet_tag);
37 Ok(packet_tag)
38}
39
40pub(crate) fn generate_key<T: crypto_traits::KeyInit, S: AsRef<[u8]>>(
52 secret: &S,
53 context: &str,
54 with_salt: Option<&[u8]>,
55) -> hopr_crypto_types::errors::Result<T> {
56 let mut out = crypto_traits::Key::<T>::default();
57
58 let mut output = create_kdf_instance(secret, context, with_salt)?;
59 output.fill(&mut out);
60
61 Ok(T::new(&out))
62}
63
64pub(crate) fn generate_key_iv<T: crypto_traits::KeyIvInit, S: AsRef<[u8]>>(
69 secret: &S,
70 context: &str,
71 with_salt: Option<&[u8]>,
72) -> hopr_crypto_types::errors::Result<T> {
73 let mut output = create_kdf_instance(secret, context, with_salt)?;
74
75 let mut key = crypto_traits::Key::<T>::default();
76 let mut iv = crypto_traits::Iv::<T>::default();
77
78 let mut out = vec![0u8; key.len() + iv.len()];
79 output.fill(&mut out);
80
81 let (v_iv, v_key) = out.split_at(iv.len());
82 iv.copy_from_slice(v_iv);
83 key.copy_from_slice(v_key);
84
85 Ok(T::new(&key, &iv))
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use elliptic_curve::hash2curve::{ExpandMsgXmd, GroupDigest};
92 use elliptic_curve::{sec1::ToEncodedPoint, ProjectivePoint, ScalarPrimitive};
93 use hex_literal::hex;
94 use hopr_crypto_types::keypairs::{ChainKeypair, Keypair};
95 use hopr_crypto_types::types::PublicKey;
96 use hopr_crypto_types::vrf::derive_vrf_parameters;
97 use k256::{Scalar, Secp256k1};
98
99 #[test]
100 fn test_sample_field_element() {
101 let secret = [1u8; SecretKey::LENGTH];
102 assert!(sample_secp256k1_field_element(&secret, "TEST_TAG").is_ok());
103 }
104
105 #[test]
106 fn test_vrf_parameter_generation() -> anyhow::Result<()> {
107 let dst = b"some DST tag";
108 let priv_key: [u8; 32] = hex!("f13233ff60e1f618525dac5f7d117bef0bad0eb0b0afb2459f9cbc57a3a987ba"); let message = hex!("f13233ff60e1f618525dac5f7d117bef0bad0eb0b0afb2459f9cbc57a3a987ba"); let keypair = ChainKeypair::from_secret(&priv_key)?;
112 let pub_key = PublicKey::from_privkey(&priv_key)?;
114
115 let params = derive_vrf_parameters(&message, &keypair, dst)?;
116
117 let cap_b =
118 Secp256k1::hash_from_bytes::<ExpandMsgXmd<Keccak256>>(&[&pub_key.to_address().as_ref(), &message], &[dst])?;
119
120 assert_eq!(
121 params.get_s_b_witness(&keypair.public().to_address(), &message, dst)?,
122 (cap_b * params.s).to_encoded_point(false)
123 );
124
125 let a: Scalar = ScalarPrimitive::<Secp256k1>::from_slice(&priv_key)?.into();
126 assert_eq!(params.get_h_v_witness(), (cap_b * a * params.h).to_encoded_point(false));
127
128 let r_v: ProjectivePoint<Secp256k1> = cap_b * params.s - params.V.clone().into_projective_point() * params.h;
129
130 let h_check = Secp256k1::hash_to_scalar::<ExpandMsgXmd<Keccak256>>(
131 &[
132 &pub_key.to_address().as_ref(),
133 ¶ms.V.as_uncompressed().as_bytes()[1..],
134 &r_v.to_affine().to_encoded_point(false).as_bytes()[1..],
135 &message,
136 ],
137 &[dst],
138 )?;
139
140 assert_eq!(h_check, params.h);
141
142 Ok(())
143 }
144}