1#![cfg_attr(not(feature = "std"), no_std)]
5
6extern crate alloc;
7
8extern crate ff;
10mod share_ff;
11
12use alloc::collections::BTreeSet;
13use alloc::vec::Vec;
14use core::convert::TryInto;
15
16use crate::ff::PrimeField;
17pub use share_ff::Evaluator;
18pub use share_ff::Share;
19pub use share_ff::{get_evaluator, interpolate, random_polynomial};
20pub use share_ff::{Fp, FpRepr, FIELD_ELEMENT_LEN};
21
22pub struct Sharks(pub u32);
26
27impl Sharks {
28 pub fn dealer_rng<R: rand::Rng>(
45 &self,
46 secret: &[u8],
47 rng: &mut R,
48 ) -> Result<Evaluator, &str> {
49 let mut polys = Vec::with_capacity(secret.len());
50
51 let secret_fp_len = secret.len() / FIELD_ELEMENT_LEN;
52 for i in 0..secret_fp_len {
53 let element = Fp::from_repr(FpRepr(
54 secret[i * FIELD_ELEMENT_LEN..(i + 1) * FIELD_ELEMENT_LEN]
55 .try_into()
56 .expect("bad chunk"),
57 ));
58 if element.is_none().into() {
59 return Err("Failed to create field element from secret");
60 }
61 let element = element.unwrap();
62 polys.push(random_polynomial(element, self.0, rng));
63 }
64
65 Ok(get_evaluator(polys))
66 }
67
68 #[cfg(feature = "std")]
79 pub fn dealer(&self, secret: &[u8]) -> Result<Evaluator, &str> {
80 let mut rng = rand::thread_rng();
81 self.dealer_rng(secret, &mut rng)
82 }
83
84 pub fn recover<'a, T>(&self, shares: T) -> Result<Vec<u8>, &str>
106 where
107 T: IntoIterator<Item = &'a Share>,
108 T::IntoIter: Iterator<Item = &'a Share>,
109 {
110 let mut share_length: Option<usize> = None;
111 let mut keys: BTreeSet<Vec<u8>> = BTreeSet::new();
112 let mut values: Vec<Share> = Vec::new();
113
114 for share in shares.into_iter() {
115 if share_length.is_none() {
116 share_length = Some(share.y.len());
117 }
118
119 if Some(share.y.len()) != share_length {
120 return Err("All shares must have the same length");
121 } else if keys.insert(share.x.to_repr().as_ref().to_vec()) {
122 values.push(share.clone());
123 }
124 }
125
126 if keys.is_empty() || (keys.len() < self.0 as usize) {
127 Err("Not enough shares to recover original secret")
128 } else {
129 interpolate(&values[0..self.0 as usize])
131 }
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::{Fp, Share, Sharks};
138 use crate::ff::{Field, PrimeField};
139 use crate::FIELD_ELEMENT_LEN;
140 use alloc::{vec, vec::Vec};
141 use core::convert::TryFrom;
142
143 impl Sharks {
144 #[cfg(not(feature = "std"))]
145 fn make_shares(
146 &self,
147 secret: &[u8],
148 ) -> Result<impl Iterator<Item = Share>, &str> {
149 use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
150 let mut rng = ChaCha8Rng::from_seed([0x90; 32]);
152 self.dealer_rng(secret, &mut rng)
153 }
154
155 #[cfg(feature = "std")]
156 fn make_shares(
157 &self,
158 secret: &[u8],
159 ) -> Result<impl Iterator<Item = Share>, &str> {
160 self.dealer(secret)
161 }
162 }
163
164 fn fp_one() -> Fp {
165 Fp::ONE
166 }
167
168 fn fp_two() -> Fp {
169 fp_one().double()
170 }
171
172 fn fp_one_repr() -> Vec<u8> {
173 fp_one().to_repr().as_ref().to_vec()
174 }
175
176 fn fp_two_repr() -> Vec<u8> {
177 (fp_one().double()).to_repr().as_ref().to_vec()
178 }
179
180 fn fp_three_repr() -> Vec<u8> {
181 (fp_two() + fp_one()).to_repr().as_ref().to_vec()
182 }
183
184 fn fp_four_repr() -> Vec<u8> {
185 (fp_two() + fp_two()).to_repr().as_ref().to_vec()
186 }
187
188 #[test]
189 fn insufficient_shares() {
190 let sharks = Sharks(500);
191 let shares: Vec<Share> = sharks
192 .make_shares(&fp_one_repr())
193 .unwrap()
194 .take(499)
195 .collect();
196 let secret = sharks.recover(&shares);
197 assert!(secret.is_err());
198 }
199
200 #[test]
201 fn duplicate_shares() {
202 let sharks = Sharks(500);
203 let mut shares: Vec<Share> = sharks
204 .make_shares(&fp_one_repr())
205 .unwrap()
206 .take(500)
207 .collect();
208 shares[1] = Share {
209 x: shares[0].x,
210 y: shares[0].y.clone(),
211 };
212 let secret = sharks.recover(&shares);
213 assert!(secret.is_err());
214 }
215
216 #[test]
217 fn integration() {
218 let sharks = Sharks(500);
219 let mut input = Vec::new();
220 input.extend(fp_one_repr());
221 input.extend(fp_two_repr());
222 input.extend(fp_three_repr());
223 input.extend(fp_four_repr());
224 let shares: Vec<Share> =
225 sharks.make_shares(&input).unwrap().take(500).collect();
226 let secret = sharks.recover(&shares).unwrap();
227 assert_eq!(secret, test_bytes());
228 }
229
230 #[test]
231 #[cfg(feature = "std")]
232 fn integration_random() {
233 let sharks = Sharks(40);
234 let mut rng = rand::thread_rng();
235 let mut input = Vec::new();
236 input.extend(fp_one_repr());
237 input.extend(fp_two_repr());
238 input.extend(fp_three_repr());
239 input.extend(fp_four_repr());
240 let evaluator = sharks.dealer(&input).unwrap();
241 let shares: Vec<Share> =
242 core::iter::repeat_with(|| evaluator.gen(&mut rng))
243 .take(55)
244 .collect();
245 let secret = sharks.recover(&shares).unwrap();
246 assert_eq!(secret, test_bytes());
247 }
248
249 fn test_bytes() -> Vec<u8> {
250 let suffix = vec![0u8; FIELD_ELEMENT_LEN - 1];
251 let mut bytes = vec![1u8; 1];
252 bytes.extend(suffix.clone()); bytes.extend(vec![2u8; 1]);
254 bytes.extend(suffix.clone()); bytes.extend(vec![3u8; 1]);
256 bytes.extend(suffix.clone()); bytes.extend(vec![4u8; 1]);
258 bytes.extend(suffix); bytes
260 }
261
262 #[test]
263 fn zero_threshold() {
264 let sharks = Sharks(0);
265 let testcase = Share::try_from(test_bytes().as_slice()).unwrap();
266 let secret = sharks.recover(&vec![testcase]);
267 assert!(secret.is_err());
268 }
269
270 #[test]
271 #[cfg(feature = "std")]
272 fn dealer_short_secret() {
273 let sharks = Sharks(2);
274
275 let secret = [0u8; FIELD_ELEMENT_LEN - 1];
277 let _dealer = sharks.dealer(&secret);
278
279 let secret = [1u8; FIELD_ELEMENT_LEN + 1];
281 let _dealer = sharks.dealer(&secret);
282 }
283}