-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpedcomm_mod.py
132 lines (95 loc) · 4.2 KB
/
pedcomm_mod.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
"""
A commitment scheme is a technique for committing to values to be verified at a later time.
It's like an sealed envelope. You put a value inside and send to a verifier. The verifier shouldn't be able to see what
is contained inside (hiding) and at the time of opening the verifier showed to able to ascertain with all certainty
that the values contained hasn't been tampered with (binding).
hiding and binding are important properties of any commitment scheme.
Hashing is a common type of commitment. A Pedersen Commitment is also a type of commitment scheme.
There many different variation of a Pedersen Commitments. In this implementation, we would work on the most
common type which has to do with modular exponentiation. Others include using elliptic curve cryptography and using Inner Product Argument as the verification mechanism.
The strength of Pedersen commitments lies in the discrete log problem.
A unique property of Pedersen Commitments is its homomorphic property which simply means that the commitment of the addtion of
two messages m1 and m2 is equal to the multiplication of there individual commitments. That is,
commit(m1) * commit(m2) = commit(m1 + m2)
A Pedersen Commitment can also be used as a Vector Commitment Scheme.
Vector Commitments Scheme are used to describe commitments that are perform on a set of values rather than a single value. Examples include Merkle Tries
and Polynomial Commitments(./polynomials/basic_polynomial_comm_using_mod)
"""
import random
from utils.number_theory import generate_random_prime
class Ped_Mod:
"""
Steps:
Verifier:
Setup:
1. Generate a large prime `q`
2. Pick a generator `g` (a number in [1, q - 1])
3. Pick a random number `s` in [1, q - 1] and compute `h` = ((g ** s) mod q)
4. The values q, g and h are sent to the prover
Opening:
1. The prover sends the commitment `c`, message `m_i` and the random number `r_i`
2. The verifier computes c_i = ((g ** m_i)(h ** r_i) mod q)
3. If c is equal to c_i then the message is valid else it's not.
4. Note: The message and the random number are denoted `m_i` and `r_i` respectively because of cases where
the prover is a malicious prover and (m, r) would not be equal to (m_i, r_i)
Prover:
1. message `m` in [1, q - 1]
2. Pick a random number `r` in [1, q - 1]
3. To get the commitment, compute `c` = ((g ** m)(h ** r) mod q)
4. The commitment `c`, the message `m` and the random number `r` is sent to the verifier for opening
"""
q = None
g = None
h = None
def __init__(self, p) -> None:
q = generate_random_prime(1, p)
g = random.randrange(1, q - 1)
s = random.randrange(1, q - 1)
h = (g ** s) % q
self.q = q
self.g = g
self.h = h
def commit(self, m: int, q: int, g: int, h: int) -> (int, int, int):
r = random.randrange(1, q - 1)
c = ((g ** m) * (h ** r)) % q
return (c, m, r)
def open(self, m_i: int, c: int, *r_i) -> bool:
sum = 0
for i in r_i:
sum += i
c_i = ((self.g ** m_i) * (self.h ** sum)) % self.q
return c == c_i
def mul_comm(self, *c):
mul = 1
for j in c:
mul *= j
c_s = mul % self.q
return c_s
# USAGE
# SETUP
p = 0xffff
ped_mod = Ped_Mod(p)
q = ped_mod.q
g = ped_mod.g # generator
h = ped_mod.h
# CREATING A COMMITMENT
m = 500 # message
c, m, r = ped_mod.commit(m, q, g, h)
# VERIFYING A COMMITMENT
status = ped_mod.open(m, c, r)
assert (status)
# SHOWING THE HOMOMORPHIC PROPERTY OF PEDERSEN COMMITMENT
m1 = 100 # message 1
m2 = 200 # message 2
m3 = 200 # message 3
m4 = 200 # message 4
m5 = 200 # message 5
c1, m_1, r_1 = ped_mod.commit(m1, q, g, h)
c2, m_2, r_2 = ped_mod.commit(m2, q, g, h)
c3, m_3, r_3 = ped_mod.commit(m3, q, g, h)
c4, m_4, r_4 = ped_mod.commit(m4, q, g, h)
c5, m_5, r_5 = ped_mod.commit(m5, q, g, h)
comms_mul = ped_mod.mul_comm(c1, c2, c3, c4, c5)
m6 = m1 + m2 + m3 + m4 + m5
status = ped_mod.open(m6, comms_mul, r_1, r_2, r_3, r_4, r_5)
assert (status)