Skip to content

Commit 1952b2a

Browse files
committedNov 11, 2023
tests: add sage prog to gen test vecs
1 parent af8ce13 commit 1952b2a

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.lock
22
/target
33
*.txt
4+
*.sage.py

‎tests/test_vectors.sage

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import secrets
2+
import hashlib
3+
4+
# Arbitrary upper bound
5+
MAX_SHARES = 32
6+
7+
# Order of secp256k1 elliptic curve
8+
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
9+
R.<x> = PolynomialRing(FiniteField(p))
10+
11+
def nonce32(D, k, n, i):
12+
sha256 = hashlib.sha256()
13+
14+
sha256.update(D.to_bytes(32, "big"))
15+
sha256.update(k.to_bytes(4, "big"))
16+
sha256.update(n.to_bytes(4, "big"))
17+
sha256.update(i.to_bytes(4, "big"))
18+
19+
sha256_hex = sha256.hexdigest()
20+
nonce = int(sha256_hex, 16) % p
21+
22+
return ZZ(nonce)
23+
24+
def sss_get_shares(D, k, n):
25+
"""
26+
Splits the secret value D into n shares; k of n are needed
27+
to reconstruct the secret.
28+
29+
D - 256-bit integer in [0, p)
30+
"""
31+
assert 0 <= D < p
32+
assert 1 < k <= n <= MAX_SHARES
33+
34+
# construct secret polynomial (degree = k-1)
35+
q = D
36+
for i in range(1, k):
37+
a_i = nonce32(int(D), int(k), int(n), int(i))
38+
assert 0 < a_i < p
39+
q += a_i * x^i
40+
41+
return [(i, q(i)) for i in range(1, n + 1)]
42+
43+
def _eval_lagrange_interpolate(t, xs, ys):
44+
"""
45+
Evaluates the iterpolated polynomial (uses lagrange basis
46+
function) at point x.
47+
t - 256-bit integer in [0, p)
48+
xs - list - x co-ordinate of the shares
49+
ys - list - y co-ordinate of the shares
50+
"""
51+
# Algorithm
52+
# 1. calc sum(y_i * delta_{j,x_i}) mod p, i = 0,1..k-1
53+
# 2. delta_{j,x_i} = {(x -x0).(x -x1)...(x -x_k-1)/
54+
# (xi-x0).(xi-x1)...(xi-x_k-1)} mod p
55+
poly = R(0)
56+
for i in range(len(ys)):
57+
delta = R(1)
58+
x_i = xs[i]
59+
y_i = ys[i]
60+
for x_j in xs:
61+
if(x_j == x_i):
62+
continue
63+
delta = delta*((x - x_j)/(x_i - x_j))
64+
poly += y_i*delta
65+
66+
return poly(t)
67+
68+
69+
def sss_recover_secret(shares):
70+
"""
71+
Recovers the secret D from the given shares.
72+
73+
shares - list of points (x_i, y_i) on the polynomial
74+
"""
75+
# Algorithm
76+
# 1. assert for distinct x_i
77+
# 2. evaluate the polynomial at 0
78+
xs = [share[0] for share in shares]
79+
ys = [share[1] for share in shares]
80+
assert len(xs) == len(set(xs))
81+
82+
return _eval_lagrange_interpolate(0, xs, ys)
83+
84+
def print_shares(shares):
85+
for i, fi in shares:
86+
print("({}, {})".format(hex(int(i)).upper(), hex(int(fi)).upper()))
87+
88+
def print_secret(secret):
89+
print("secret: {}".format(hex(int(secret)).upper()))
90+
91+
def generate_test_vectors():
92+
seckey = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
93+
94+
print("test_vector1:")
95+
shares1 = sss_get_shares(seckey, 2, 3)
96+
print_shares(shares1)
97+
print_secret(sss_recover_secret(shares1))
98+
99+
print("test_vector2:")
100+
shares2 = sss_get_shares(seckey, 3, 5)
101+
print_shares(shares2)
102+
print_secret(sss_recover_secret(shares1))
103+
104+
print("test_vector3:")
105+
shares3 = sss_get_shares(seckey, 4, 7)
106+
print_shares(shares3)
107+
print_secret(sss_recover_secret(shares1))
108+
109+
if __name__ == '__main__':
110+
generate_test_vectors()

0 commit comments

Comments
 (0)