1
1
use hacspec_lib:: * ;
2
+ use hacspec_sha256:: * ;
2
3
3
- // arbitrary upper bound
4
- const MAX_SHARES : usize = 32 ;
5
4
6
5
// order of secp256k1 elliptic curve
7
6
public_nat_mod ! (
@@ -11,17 +10,85 @@ public_nat_mod!(
11
10
modulo_value: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
12
11
) ;
13
12
14
- // t & n remain const for every shares in a set
15
- # [ allow ( non_camel_case_types ) ]
16
- pub enum ShamirShare {
17
- x ( FieldElement ) ,
18
- y ( FieldElement ) ,
19
- t ( usize ) ,
20
- n ( usize ) ,
21
- }
13
+ type Point = ( FieldElement , FieldElement ) ;
14
+
15
+ // 2nd arg -> t, 3rd arg -> n
16
+ //todo: use named struct instead?
17
+ pub type ShamirShare = ( Point , usize , usize ) ;
18
+
19
+ bytes ! ( Bytes32 , 32 ) ;
20
+ type SharedSecret = Bytes32 ;
22
21
23
22
// APIs Planned:
24
- // 1. generate_shares(secret: FieldElement , t: usize, n: usize) -> & Seq<ShamirShare>
23
+ // 1. generate_shares(secret: ByteSeq , t: usize, n: usize) -> Seq<ShamirShare>
25
24
// 1.1 we use `usize` (instead of `FieldElement`) for t and n for simplicity
26
25
// 2. recover_secret(shares: &Seq<ShamirShare>) -> FieldElement
27
- // 2.1 eval_lagrange_poly(shares &Seq<ShamirShare>) -> FieldElement
26
+ // 2.1 lagrange_interpolate(shares &Seq<ShamirShare>) -> FieldElement
27
+
28
+ // avoids tagged hash for simplicity
29
+ fn nonce32 (
30
+ secret : SharedSecret ,
31
+ t : usize ,
32
+ n : usize ,
33
+ i : usize ,
34
+ ) -> Bytes32 {
35
+ // convert t, n, and i into bytes of secret value
36
+ let t = U32 :: classify ( t as u32 ) ;
37
+ let n = U32 :: classify ( n as u32 ) ;
38
+ let i = U32 :: classify ( i as u32 ) ;
39
+ let hash_inp = ByteSeq :: from_seq ( & secret)
40
+ . concat ( & U32_to_be_bytes ( t) )
41
+ . concat ( & U32_to_be_bytes ( n) )
42
+ . concat ( & U32_to_be_bytes ( i) ) ;
43
+ let hash = sha256 ( & hash_inp) ;
44
+ Bytes32 :: from_seq ( & hash)
45
+ }
46
+
47
+ //todo: use hacspec internal `poly!` type instead?
48
+ // computes poly(x)
49
+ fn eval_poly (
50
+ poly : & Seq < FieldElement > ,
51
+ x : FieldElement ,
52
+ ) -> FieldElement {
53
+ let mut res = poly[ 0 ] ;
54
+ let len = poly. len ( ) ;
55
+
56
+ for i in 1 ..( len-1 ) {
57
+ res = res + poly[ i] * ( x. pow ( i as u128 ) ) ;
58
+ }
59
+
60
+ res
61
+ }
62
+
63
+ pub fn generate_shares (
64
+ secret : SharedSecret ,
65
+ t : usize ,
66
+ n : usize ,
67
+ ) -> Seq < ShamirShare > {
68
+ //todo: hacspec prevents using `assert!`
69
+ // - use `u32Word` for t, and n instead?
70
+ // assert!(t <= u32::MAX as usize);
71
+ // assert!(n <= u32::MAX as usize);
72
+
73
+ let mut out = Seq :: < ShamirShare > :: new ( n) ;
74
+ let mut poly = Seq :: < FieldElement > :: new ( t) ;
75
+
76
+ poly[ 0 ] = FieldElement :: from_byte_seq_be ( & secret) ;
77
+
78
+ // generate random coefficients for `poly`
79
+ for i in 1 ..( t-1 ) {
80
+ let entropy = nonce32 ( secret, t, n, i) ;
81
+ let coeff = FieldElement :: from_byte_seq_be ( & entropy) ;
82
+ poly[ i] = coeff;
83
+ }
84
+
85
+ for i in 0 ..( n-1 ) {
86
+ let xi = FieldElement :: from_literal ( i as u128 ) ;
87
+ let yi = eval_poly ( & poly, xi) ;
88
+ let si: ShamirShare = ( ( xi, yi) , t, n) ;
89
+
90
+ out[ i] = si;
91
+ }
92
+
93
+ out
94
+ }
0 commit comments