1use aztec_core::types::{Fr, GrumpkinScalar};
4use sha2::{Digest, Sha512};
5
6pub fn sha512_to_grumpkin_scalar(secret_key: &Fr, domain_separator: u32) -> GrumpkinScalar {
14 let mut input = [0u8; 36];
16 input[..32].copy_from_slice(&secret_key.to_be_bytes());
17 input[32..36].copy_from_slice(&domain_separator.to_be_bytes());
18
19 let hash = Sha512::digest(input); GrumpkinScalar::from_be_bytes_mod_order(&hash)
24}
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29 use aztec_core::constants::domain_separator;
30
31 #[test]
32 fn sha512_input_buffer_is_36_bytes() {
33 let sk = Fr::from(8923u64);
35 let sep = domain_separator::NHK_M;
36
37 let mut expected_input = [0u8; 36];
38 expected_input[..32].copy_from_slice(&sk.to_be_bytes());
39 expected_input[32..36].copy_from_slice(&sep.to_be_bytes());
40
41 let result = sha512_to_grumpkin_scalar(&sk, sep);
43 assert!(!result.is_zero());
44 }
45
46 #[test]
47 fn sha512_deterministic() {
48 let sk = Fr::from(42u64);
49 let r1 = sha512_to_grumpkin_scalar(&sk, 123);
50 let r2 = sha512_to_grumpkin_scalar(&sk, 123);
51 assert_eq!(r1, r2);
52 }
53
54 #[test]
55 fn sha512_different_separators_produce_different_results() {
56 let sk = Fr::from(42u64);
57 let r1 = sha512_to_grumpkin_scalar(&sk, domain_separator::NHK_M);
58 let r2 = sha512_to_grumpkin_scalar(&sk, domain_separator::IVSK_M);
59 assert_ne!(r1, r2);
60 }
61}