hash_based_signatures/signature/winternitz/
domination_free_function.rs1use crate::signature::winternitz::d::D;
2use crate::signature::HashType;
3use crate::utils::{bits_to_unsigned_int, get_least_significant_bits};
4
5fn bitstring_to_integers(bit_string: &Vec<bool>, d: &D) -> Vec<u8> {
6 let n_elements = bit_string.len() / d.bits_to_combine();
7 (0..n_elements)
8 .map(|i| {
9 let start_bit = i * d.bits_to_combine();
10 let end_bit = start_bit + d.bits_to_combine();
11 bits_to_unsigned_int(&bit_string[start_bit..end_bit])
12 })
13 .collect()
14}
15
16pub fn domination_free_function(input: HashType, d: &D) -> Vec<u8> {
19 let bit_string: Vec<bool> = input
20 .map(|x| get_least_significant_bits(x as usize, 8))
21 .into_iter()
22 .flatten()
23 .collect();
24
25 let mut result = Vec::new();
26 let n0 = 256 / d.bits_to_combine();
27 let mut c = d.d * (n0 as u64);
28 for x in bitstring_to_integers(&bit_string, d) {
29 result.push(x);
30 c -= x as u64;
31 }
32
33 let c_bitstring = get_least_significant_bits(c as usize, d.bits_c() as usize);
34
35 result.append(&mut bitstring_to_integers(&c_bitstring, d));
36
37 result
38}
39
40#[cfg(test)]
41mod tests {
42 use crate::signature::winternitz::domination_free_function::{domination_free_function, D};
43 use rand::prelude::*;
44 use rand_chacha::ChaCha20Rng;
45
46 #[test]
47 fn test_domination_free_function_0s_d1() {
48 let result = domination_free_function([0; 32], &D::new(1));
49 let mut expected = vec![0u8; 256];
50
51 expected.extend([1, 0, 0, 0, 0, 0, 0, 0, 0]);
53
54 assert_eq!(result, expected);
55 }
56
57 #[test]
58 fn test_domination_free_function_0s_d3() {
59 let result = domination_free_function([0; 32], &D::new(3));
60 let mut expected = vec![0u8; 128];
61
62 expected.extend([1, 2, 0, 0, 0]);
66
67 assert_eq!(result, expected);
68 }
69
70 #[test]
71 fn test_domination_free_function_0s_d15() {
72 let result = domination_free_function([0; 32], &D::new(15));
73 let mut expected = vec![0u8; 64];
74
75 expected.extend([0x3, 0xc, 0x0]);
79
80 assert_eq!(result, expected);
81 }
82
83 #[test]
84 fn test_domination_free_function_0s_d255() {
85 let result = domination_free_function([0; 32], &D::new(255));
86 let mut expected = vec![0u8; 32];
87
88 expected.extend([0x1f, 0xe0]);
92
93 assert_eq!(result, expected);
94 }
95
96 #[test]
97 fn test_domination_free_function_1s_d255() {
98 let result = domination_free_function([255; 32], &D::new(255));
99 let mut expected = vec![255u8; 32];
100
101 expected.extend([0, 0]);
104
105 assert_eq!(result, expected);
106 }
107
108 fn get_domination_free_vectors_on_random_data(d: &D, count: usize) -> Vec<Vec<u8>> {
109 let mut rng = ChaCha20Rng::from_seed([0; 32]);
110 let mut hash = [0u8; 32];
111 (0..count)
112 .map(|_| {
113 rng.fill_bytes(&mut hash);
114 domination_free_function(hash, d)
115 })
116 .collect()
117 }
118
119 fn assert_no_domination(domination_free_vectors: &Vec<Vec<u8>>) {
120 for i in 0..domination_free_vectors.len() {
121 for j in 0..domination_free_vectors.len() {
122 if i != j {
123 let vec1 = &domination_free_vectors[i];
127 let vec2 = &domination_free_vectors[j];
128
129 let v1_dominates_sometimes =
130 vec1.iter().zip(vec2).map(|(v1, v2)| v1 > v2).max().unwrap();
131 assert!(v1_dominates_sometimes);
132 }
133 }
134 }
135 }
136
137 #[test]
138 fn domination_free_on_random_data_d1() {
139 let domination_free_vectors = get_domination_free_vectors_on_random_data(&D::new(1), 1000);
140 assert_no_domination(&domination_free_vectors);
141 }
142
143 #[test]
144 fn domination_free_on_random_data_d3() {
145 let domination_free_vectors = get_domination_free_vectors_on_random_data(&D::new(3), 1000);
146 assert_no_domination(&domination_free_vectors);
147 }
148
149 #[test]
150 fn domination_free_on_random_data_d15() {
151 let domination_free_vectors = get_domination_free_vectors_on_random_data(&D::new(15), 1000);
152 assert_no_domination(&domination_free_vectors);
153 }
154
155 #[test]
156 fn domination_free_on_random_data_d255() {
157 let domination_free_vectors =
158 get_domination_free_vectors_on_random_data(&D::new(255), 1000);
159 assert_no_domination(&domination_free_vectors);
160 }
161}