pairing_plus/
hash_to_field.rs1use digest::generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
7use digest::{BlockInput, Digest, ExtendableOutput, Input};
8use std::marker::PhantomData;
9
10pub fn hash_to_field<T, X>(msg: &[u8], dst: &[u8], count: usize) -> Vec<T>
12where
13 T: FromRO,
14 X: ExpandMsg,
15{
16 let len_per_elm = <T as FromRO>::Length::to_usize();
17 let len_in_bytes = count * len_per_elm;
18 let pseudo_random_bytes = X::expand_message(msg, dst, len_in_bytes);
19
20 let mut ret = Vec::<T>::with_capacity(count);
21 for idx in 0..count {
22 let bytes_to_convert = &pseudo_random_bytes[idx * len_per_elm..(idx + 1) * len_per_elm];
23 let bytes_arr = GenericArray::<u8, <T as FromRO>::Length>::from_slice(bytes_to_convert);
24 ret.push(T::from_ro(bytes_arr));
25 }
26
27 ret
28}
29
30pub trait FromRO {
32 type Length: ArrayLength<u8>;
33
34 fn from_ro(okm: &GenericArray<u8, <Self as FromRO>::Length>) -> Self;
35}
36
37impl<T: BaseFromRO> FromRO for T {
39 type Length = <T as BaseFromRO>::BaseLength;
40
41 fn from_ro(okm: &GenericArray<u8, <Self as FromRO>::Length>) -> T {
42 T::from_okm(okm)
43 }
44}
45
46pub trait BaseFromRO {
49 type BaseLength: ArrayLength<u8>;
50
51 fn from_okm(okm: &GenericArray<u8, <Self as BaseFromRO>::BaseLength>) -> Self;
52}
53
54pub trait ExpandMsg {
56 fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec<u8>;
57}
58
59#[derive(Debug)]
61pub struct ExpandMsgXof<HashT> {
62 phantom: PhantomData<HashT>,
63}
64
65impl<HashT> ExpandMsg for ExpandMsgXof<HashT>
67where
68 HashT: Default + ExtendableOutput + Input,
69{
70 fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec<u8> {
71 HashT::default()
72 .chain(msg)
73 .chain([
74 (len_in_bytes >> 8) as u8,
75 len_in_bytes as u8,
76 ])
77 .chain(dst)
78 .chain([dst.len() as u8])
79 .vec_result(len_in_bytes)
80 }
81}
82
83#[derive(Debug)]
85pub struct ExpandMsgXmd<HashT> {
86 phantom: PhantomData<HashT>,
87}
88
89impl<HashT> ExpandMsg for ExpandMsgXmd<HashT>
91where
92 HashT: Digest + BlockInput,
93{
94 fn expand_message(msg: &[u8], dst: &[u8], len_in_bytes: usize) -> Vec<u8> {
95 let b_in_bytes = <HashT as Digest>::OutputSize::to_usize();
96 let ell = (len_in_bytes + b_in_bytes - 1) / b_in_bytes;
97 if ell > 255 {
98 panic!("ell was too big in expand_message_xmd");
99 }
100 let b_0 = HashT::new()
101 .chain(GenericArray::<u8, <HashT as BlockInput>::BlockSize>::default())
102 .chain(msg)
103 .chain([
104 (len_in_bytes >> 8) as u8,
105 len_in_bytes as u8,
106 0u8,
107 ])
108 .chain(dst)
109 .chain([dst.len() as u8])
110 .result();
111
112 let mut b_vals = Vec::<u8>::with_capacity(ell * b_in_bytes);
113 b_vals.extend_from_slice(
115 HashT::new()
116 .chain(&b_0[..])
117 .chain([1u8])
118 .chain(dst)
119 .chain([dst.len() as u8])
120 .result()
121 .as_ref(),
122 );
123
124 for idx in 1..ell {
125 let mut tmp = GenericArray::<u8, <HashT as Digest>::OutputSize>::default();
127 b_0.iter()
128 .zip(&b_vals[(idx - 1) * b_in_bytes..idx * b_in_bytes])
129 .enumerate()
130 .for_each(|(jdx, (b0val, bi1val))| tmp[jdx] = b0val ^ bi1val);
131 b_vals.extend_from_slice(
132 HashT::new()
133 .chain(tmp)
134 .chain([(idx + 1) as u8])
135 .chain(dst)
136 .chain([dst.len() as u8])
137 .result()
138 .as_ref(),
139 );
140 }
141
142 b_vals.truncate(len_in_bytes);
143 b_vals
144 }
145}