1use star_sharks::Sharks;
9use std::convert::{TryFrom, TryInto};
10use std::error::Error;
11use std::fmt;
12use strobe_rs::{SecParam, Strobe};
13use zeroize::{Zeroize, ZeroizeOnDrop};
14
15mod strobe_rng;
16use strobe_rng::StrobeRng;
17
18pub const ACCESS_STRUCTURE_LENGTH: usize = 4;
20
21pub const MAC_LENGTH: usize = 64;
23
24#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
28pub struct AccessStructure {
29 threshold: u32,
30}
31
32pub fn store_u32(u: u32, out: &mut Vec<u8>) {
34 out.extend(u.to_le_bytes());
35}
36
37pub fn load_u32(bytes: &[u8]) -> Option<u32> {
39 if bytes.len() != 4 {
40 return None;
41 }
42
43 let mut bits: [u8; 4] = [0u8; 4];
44 bits.copy_from_slice(bytes);
45 Some(u32::from_le_bytes(bits))
46}
47
48pub fn store_bytes(s: &[u8], out: &mut Vec<u8>) {
54 store_u32(s.len() as u32, out);
55 out.extend(s);
56}
57
58pub fn load_bytes(bytes: &[u8]) -> Option<&[u8]> {
67 if bytes.len() < 4 {
68 return None;
69 }
70
71 let len: u32 = load_u32(&bytes[..4])?;
72 if bytes.len() < (4 + len) as usize {
73 return None;
74 }
75
76 Some(&bytes[4..4 + len as usize])
77}
78
79impl AccessStructure {
84 pub fn to_bytes(&self) -> [u8; ACCESS_STRUCTURE_LENGTH] {
86 self.threshold.to_le_bytes()
87 }
88
89 pub fn from_bytes(bytes: &[u8]) -> Option<AccessStructure> {
94 let threshold = load_u32(bytes)?;
95 Some(AccessStructure { threshold })
96 }
97}
98
99#[allow(non_snake_case)]
100impl From<AccessStructure> for Sharks {
101 fn from(A: AccessStructure) -> Sharks {
102 Sharks(A.threshold)
103 }
104}
105
106#[allow(non_snake_case)]
114#[derive(Clone, ZeroizeOnDrop)]
115pub struct Commune {
116 A: AccessStructure,
118 M: Vec<u8>,
120 R: Vec<u8>,
122 T: Option<Strobe>,
124}
125
126#[allow(non_snake_case)]
131#[derive(Clone, Eq, PartialEq, Zeroize)]
132pub struct Share {
133 A: AccessStructure,
134 S: star_sharks::Share,
135 C: Vec<u8>,
137 D: Vec<u8>,
139 J: [u8; MAC_LENGTH],
141 T: (),
142}
143
144impl fmt::Debug for Share {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 f.debug_struct("Share").field("S", &self.S).finish()
147 }
148}
149
150impl Share {
151 pub fn to_bytes(&self) -> Vec<u8> {
152 let mut out: Vec<u8> = Vec::new();
153
154 out.extend(self.A.to_bytes());
156
157 store_bytes(&Vec::from(&self.S), &mut out);
159
160 store_bytes(&self.C, &mut out);
162
163 store_bytes(&self.D, &mut out);
165
166 out.extend(self.J);
168
169 out
170 }
171
172 pub fn from_bytes(bytes: &[u8]) -> Option<Share> {
173 let mut slice = bytes;
174
175 let a = AccessStructure::from_bytes(&slice[..ACCESS_STRUCTURE_LENGTH])?;
177 slice = &slice[ACCESS_STRUCTURE_LENGTH..];
178
179 let sb = load_bytes(slice)?;
181 slice = &slice[4 + sb.len()..];
182
183 let c = load_bytes(slice)?;
185 slice = &slice[4 + c.len()..];
186
187 let d = load_bytes(slice)?;
189 slice = &slice[4 + d.len()..];
190
191 let j: [u8; MAC_LENGTH] = slice.try_into().ok()?;
193
194 Some(Share {
195 A: a,
196 S: star_sharks::Share::try_from(sb).ok()?,
197 C: c.to_vec(),
198 D: d.to_vec(),
199 J: j,
200 T: (),
201 })
202 }
203}
204
205#[allow(non_snake_case)]
206impl Commune {
207 pub fn new(
208 threshold: u32,
209 message: Vec<u8>,
210 randomness: Vec<u8>,
211 transcript: Option<Strobe>,
212 ) -> Self {
213 Commune {
214 A: AccessStructure { threshold },
215 M: message,
216 R: randomness,
217 T: transcript,
218 }
219 }
220
221 pub fn share(self) -> Result<Share, Box<dyn Error>> {
224 let mut transcript = self
226 .T
227 .clone()
228 .unwrap_or_else(|| Strobe::new(b"adss", SecParam::B128));
229 transcript.ad(&self.A.to_bytes(), false);
230 transcript.ad(&self.M, false);
231 transcript.key(&self.R, false);
232
233 let mut J = [0u8; 64];
235 transcript.send_mac(&mut J, false);
236
237 let mut K = [0u8; 16];
239 transcript.prf(&mut K, false);
240
241 let mut L: StrobeRng = transcript.into();
243
244 let mut key = Strobe::new(b"adss encrypt", SecParam::B128);
245 key.key(&K, false);
246
247 let mut C: Vec<u8> = vec![0; self.M.len()];
249 C.copy_from_slice(&self.M);
250 key.send_enc(&mut C, false);
251
252 let mut D: Vec<u8> = vec![0; self.R.len()];
254 D.copy_from_slice(&self.R);
255 key.send_enc(&mut D, false);
256
257 let mut K_vec: Vec<u8> = K.to_vec();
259 K_vec.extend(vec![0u8; 16]);
260 let polys = Sharks::from(self.A.clone()).dealer_rng(&K_vec, &mut L)?;
261 let S = polys.gen(&mut rand::rngs::OsRng);
262 Ok(Share {
263 A: self.A.clone(),
264 S,
265 C,
266 D,
267 J,
268 T: (),
269 })
270 }
271
272 pub fn get_message(&self) -> Vec<u8> {
273 self.M.clone()
274 }
275
276 fn verify(&self, J: &[u8; MAC_LENGTH]) -> Result<(), Box<dyn Error>> {
277 let mut transcript = self
278 .clone()
279 .T
280 .clone()
281 .unwrap_or_else(|| Strobe::new(b"adss", SecParam::B128));
282 transcript.ad(&self.A.to_bytes(), false);
283 transcript.ad(&self.M, false);
284 transcript.key(&self.R, false);
285
286 transcript
287 .recv_mac(J)
288 .map_err(|_| "Mac validation failed".into())
289 }
290}
291
292#[allow(non_snake_case)]
293pub fn recover<'a, T>(shares: T) -> Result<Commune, Box<dyn Error>>
296where
297 T: IntoIterator<Item = &'a Share>,
298 T::IntoIter: Iterator<Item = &'a Share>,
299{
300 let mut shares = shares.into_iter().peekable();
301 let s = &(*shares.peek().ok_or("no shares passed")?).clone();
302 let shares: Vec<star_sharks::Share> = shares.cloned().map(|s| s.S).collect();
303 let key = Sharks::from(s.A.clone()).recover(&shares)?;
304 let K = key[..16].to_vec();
305
306 let mut key = Strobe::new(b"adss encrypt", SecParam::B128);
307 key.key(&K, false);
308
309 let mut M: Vec<u8> = vec![0; s.C.len()];
311 M.copy_from_slice(&s.C);
312 key.recv_enc(&mut M, false);
313
314 let mut R: Vec<u8> = vec![0; s.D.len()];
316 R.copy_from_slice(&s.D);
317 key.recv_enc(&mut R, false);
318
319 let c = Commune {
320 A: s.A.clone(),
321 M,
322 R,
323 T: None,
324 };
325
326 c.verify(&s.J.clone())?;
327 Ok(c)
328}
329
330#[cfg(test)]
331mod tests {
332 use core::iter;
333
334 use crate::*;
335
336 #[test]
337 fn serialization_u32() {
338 for &i in &[0, 10, 100, u32::MAX] {
339 let mut out: Vec<u8> = Vec::new();
340 store_u32(i, &mut out);
341 assert_eq!(load_u32(out.as_slice()), Some(i));
342 }
343 }
344
345 #[test]
346 fn serialization_empty_bytes() {
347 let mut out: Vec<u8> = Vec::new();
348 store_bytes(Vec::new().as_slice(), &mut out);
349 assert_eq!(load_bytes(out.as_slice()), Some(&[] as &[u8]));
350 }
351
352 #[test]
353 fn serialization_bytes() {
354 let mut out: Vec<u8> = Vec::new();
355 let bytes: &[u8] = &[0, 1, 10, 100];
356 store_bytes(bytes, &mut out);
357 assert_eq!(load_bytes(out.as_slice()), Some(bytes));
358 }
359
360 #[test]
361 fn serialization_access_structure() {
362 for i in &[0, 10, 100, u32::MAX] {
363 let a = AccessStructure { threshold: *i };
364 let s: &[u8] = &a.to_bytes()[..];
365 assert_eq!(AccessStructure::from_bytes(s), Some(a));
366 }
367 }
368
369 #[test]
370 fn serialization_share() {
371 let c = Commune {
372 A: AccessStructure { threshold: 50 },
373 M: vec![1, 2, 3, 4],
374 R: vec![5, 6, 7, 8],
375 T: None,
376 };
377
378 for share in iter::repeat_with(|| c.clone().share()).take(150) {
379 let share = share.unwrap();
380 let s = share.to_bytes();
381 assert_eq!(Share::from_bytes(s.as_slice()), Some(share));
382
383 assert_eq!(Share::from_bytes(&s[..s.len() - 7]), None);
385 }
386 }
387
388 #[test]
389 fn it_works() {
390 let c = Commune {
391 A: AccessStructure { threshold: 50 },
392 M: vec![1, 2, 3, 4],
393 R: vec![5, 6, 7, 8],
394 T: None,
395 };
396
397 let shares: Vec<Share> = iter::repeat_with(|| c.clone().share().unwrap())
398 .take(150)
399 .collect();
400
401 let recovered = recover(&shares).unwrap();
402
403 assert_eq!(c.M, recovered.M);
404 }
405}