Skip to content

Commit af8ce13

Browse files
committed
sss: add generate_shares API
1 parent 2fe13fa commit af8ce13

File tree

2 files changed

+81
-13
lines changed

2 files changed

+81
-13
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ edition = "2021"
88
path = "src/sss.rs"
99

1010
[dependencies]
11-
hacspec-lib = { git = "https://github.com/hacspec/hacspec/", branch = "master" }
11+
hacspec-lib = { git = "https://github.com/hacspec/hacspec/", branch = "master" }
12+
hacspec-sha256 = { git = "https://github.com/hacspec/hacspec/", branch = "master" }

src/sss.rs

+79-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use hacspec_lib::*;
2+
use hacspec_sha256::*;
23

3-
// arbitrary upper bound
4-
const MAX_SHARES: usize = 32;
54

65
// order of secp256k1 elliptic curve
76
public_nat_mod!(
@@ -11,17 +10,85 @@ public_nat_mod!(
1110
modulo_value: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
1211
);
1312

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;
2221

2322
// 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>
2524
// 1.1 we use `usize` (instead of `FieldElement`) for t and n for simplicity
2625
// 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

Comments
 (0)