-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpedersen_commitment.py
138 lines (103 loc) · 3.48 KB
/
pedersen_commitment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from pypcs.curve import Fp, Fr, ec_mul, G1Point
import random
# (HV) Computational Zero-Knowledge pedersen Protocol
class PedersenParams:
def __init__(self):
self.G = G1Point.ec_gen_group1()
self.H = self.generateH()
@staticmethod
def generateH() -> G1Point:
# generate a random point as H
r = Fr.rand(random.Random("hash-to-point"))
return ec_mul(G1Point.ec_gen_group1(), r)
def commit(sk: Fr, rho: Fr, pp: PedersenParams) -> G1Point:
"""
Computationally hiding
Statistically binding
"""
return ec_mul(G1Point.ec_gen_group1(), sk) + ec_mul(pp.H, rho)
class Prover:
sk: Fr
rho: Fr
r: Fr
r_rho: Fr
pk: G1Point
pp: PedersenParams
rnd_gen: random.Random
def __init__(self, sk: Fr, rho: Fr):
self.sk = sk
self.rho = rho
self.pp = PedersenParams()
self.pk = commit(sk, rho, self.pp)
self.rnd_gen = random.Random("pedersen-prover")
def round1(self) -> G1Point:
self.r = Fr.rand(self.rnd_gen)
self.r_rho = Fr.rand(self.rnd_gen)
R = commit(self.r, self.r_rho, self.pp)
return R
def round3(self, c: Fr) -> tuple[Fr, Fr]:
z = self.r + c * self.sk
z_rho = self.r_rho + c * self.rho
return z, z_rho
class Verifier:
pk: G1Point
pp: PedersenParams
rnd_gen: random.Random
def __init__(self, pk: G1Point, pp: PedersenParams):
self.pk = pk
self.pp = pp
self.rnd_gen = random.Random("pederson-verifier")
def round2(self: G1Point) -> Fr:
c = Fr.rand(self.rnd_gen)
return c
def verify(self, R: G1Point, c: Fr, z: Fr, z_rho: Fr) -> bool:
"""
[z;z_rho] ?= [r;r_rho] + c * pk
"""
return commit(z, z_rho, self.pp) == R + ec_mul(self.pk, c)
def run_pedersen(sk: Fr, rho: Fr, pp: PedersenParams) -> bool:
prover = Prover(sk, rho)
verifier = Verifier(prover.pk, pp)
R = prover.round1()
c = verifier.round2()
z, z_rho = prover.round3(c)
return verifier.verify(R, c, z, z_rho)
def simulate(prover_pk: G1Point, verifier: Verifier) -> Fr:
pp = verifier.pp
# 1 simulator does Round 1 of prover
r = Fr(1)
r_rho = Fr(1)
R = commit(r, r_rho, pp)
# 2. simulator invoke Round 2 of verifier
st = verifier.rnd_gen.getstate()
c = verifier.round2()
# 3. simulator does Round 3 of prover
z_star = Fr.rand(random.Random("pedersen-sim-z"))
z_rho_star = Fr.rand(random.Random("pedersen-sim-z-rho"))
Z_star = commit(z_star, z_rho_star, pp)
R_star = Z_star - ec_mul(prover_pk, c)
verifier.rnd_gen.setstate(st)
c_star = verifier.round2()
assert c == c_star
return verifier.verify(R_star, c, z_star, z_rho_star)
def extract(prover: Prover) -> tuple[Fr, Fr]:
rng = random.Random("pedersen-extract")
R = prover.round1()
c_1 = Fr.rand(rng)
c_2 = Fr.rand(rng)
z_1, z_rho_1 = prover.round3(c_1)
z_2, z_rho_2 = prover.round3(c_2)
sk = (z_2 - z_1) / (c_2 - c_1)
rho = (z_rho_2 - z_rho_1) / (c_2 - c_1)
return sk, rho
if __name__ == "__main__":
pedersen_params = PedersenParams()
sk = Fr(31)
rho = Fr(19)
print(f"sk: {sk};{rho}")
print(f"pk: {commit(sk, rho, pedersen_params)}")
print(f"?: {run_pedersen(sk, rho, pedersen_params)}")
print(
f"?: {simulate(commit(sk, rho, pedersen_params), Verifier(commit(sk, rho, pedersen_params), pedersen_params))}"
)
print(f"?: {extract(Prover(sk, rho))}")