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