paillier 1.0.0 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f63285c7920e05242437975a03efa519083e7eed
4
- data.tar.gz: dd8ac8fd45845371b140c96bcba512e4ece04607
2
+ SHA256:
3
+ metadata.gz: 784166f6728fa330be600b47c2be1a643ff20471b6029723083a94806681a93a
4
+ data.tar.gz: '05960d00f769c0be21772270addb3a9f247b925621b2ebc7d78d7a86e8aac5fc'
5
5
  SHA512:
6
- metadata.gz: 7951656a310e1b9a1ad402de9b765a51be1a690537cb24390527abfecf67389866921c35bc2b97174097fa65acabeb52686c5c14009af1c1f297bf950442728c
7
- data.tar.gz: bbbc5f266370f5f55d87932d5744acf4c518208eae95237f10da1b41f73ed5cfebd048b20bf62ad7520a89b435fa46e5057d6ee7bef78e834c025fd73045ce6b
6
+ metadata.gz: 9288c168ac05ed5584d6c7878ec248b0dea02b0c3c9bd866c810c5f4a962677fc65a6338573835eb6e4e651fdb39bb4239d561f7600ec6898e3b1adfae55dff6
7
+ data.tar.gz: 84c1f5a371d5ba2e6be59c3193b9a1814882cff4a843549f5e0d10842869c2b074e1402f4fe359a71428e2d49ed07545cc92c5ad8dd218f9df04083d1d2b6cae
@@ -8,11 +8,10 @@ require 'bigdecimal/math' # For 'log'
8
8
  require_relative 'paillier/primes'
9
9
  require_relative 'paillier/keys'
10
10
  require_relative 'paillier/signatures'
11
+ require_relative 'paillier/zkp'
11
12
 
12
13
  module Paillier
13
14
 
14
- KeySize = 2048
15
-
16
15
  def self.gcd(u,v) # :nodoc:
17
16
  while(v > 0)
18
17
  u, v = v, u % v
@@ -100,7 +99,7 @@ module Paillier
100
99
  while( true )
101
100
  # We have to use BigMath here to make sure 'log' doesn't round
102
101
  # to infinity and throw an exception
103
- big_n = BigDecimal.new(pub.n)
102
+ big_n = BigDecimal(pub.n)
104
103
  r = Primes.generateCoprime(BigMath.log(big_n, 2).round, pub.n)
105
104
  if( r > 0 and r < pub.n )
106
105
  break
@@ -123,8 +122,11 @@ module Paillier
123
122
  #
124
123
  # Arguments:
125
124
  # publicKey: (Paillier::PublicKey)
126
- # plaintext: (Int)
125
+ # plaintext: (Int, OpenSSL::BN, String)
127
126
  def self.encrypt(publicKey, plaintext)
127
+ if( plaintext.is_a?(String) )
128
+ plaintext = OpenSSL::BN.new(plaintext)
129
+ end
128
130
  return rEncrypt(publicKey, plaintext)[1]
129
131
  end
130
132
 
@@ -136,9 +138,15 @@ module Paillier
136
138
  #
137
139
  # Arguments:
138
140
  # publicKey: (Paillier::PublicKey)
139
- # a: (Int)
140
- # b: (Int)
141
+ # a: (Int, OpenSSL::BN, String)
142
+ # b: (Int, OpenSSL::BN, String)
141
143
  def self.eAdd(publicKey, a, b)
144
+ if( a.is_a?(String) )
145
+ a = OpenSSL::BN.new(a)
146
+ end
147
+ if( b.is_a?(String) )
148
+ b = OpenSSL::BN.new(b)
149
+ end
142
150
  return a.to_bn.mod_mul(b, publicKey.n_sq)
143
151
  end
144
152
 
@@ -150,9 +158,15 @@ module Paillier
150
158
  #
151
159
  # Arguments:
152
160
  # publicKey: (Paillier::PublicKey)
153
- # a: (Int)
154
- # b: (Int)
161
+ # a: (Int, OpenSSL::BN, String)
162
+ # n: (Int, OpenSSL::BN, String)
155
163
  def self.eAddConst(publicKey, a, n)
164
+ if( a.is_a?(String) )
165
+ a = OpenSSL::BN.new(a)
166
+ end
167
+ if( n.is_a?(String) )
168
+ n = OpenSSL::BN.new(n)
169
+ end
156
170
  return a.to_bn.mod_mul(modPow(publicKey.g, n, publicKey.n_sq), publicKey.n_sq)
157
171
  end
158
172
 
@@ -164,7 +178,15 @@ module Paillier
164
178
  #
165
179
  # Arguments:
166
180
  # publicKey: (Paillier::PublicKey)
181
+ # a: (Int, OpenSSL::BN, String)
182
+ # n: (Int, OpenSSL::BN, String)
167
183
  def self.eMulConst(publicKey, a, n)
184
+ if( a.is_a?(String) )
185
+ a = OpenSSL::BN.new(a)
186
+ end
187
+ if( n.is_a?(String) )
188
+ n = OpenSSL::BN.new(n)
189
+ end
168
190
  return modPow(a, n, publicKey.n_sq)
169
191
  end
170
192
 
@@ -177,8 +199,11 @@ module Paillier
177
199
  # Arguments:
178
200
  # privKey: (Paillier::PrivateKey)
179
201
  # pubKey: (Paillier::PublicKey)
180
- # ciphertext: (Int)
202
+ # ciphertext: (Int, OpenSSL::BN, String)
181
203
  def self.decrypt(privKey, pubKey, ciphertext)
204
+ if( ciphertext.is_a?(String) )
205
+ ciphertext = OpenSSL::BN.new(ciphertext)
206
+ end
182
207
  # We want to run: x = ((cipher ** priv.l) % pub.n_sq) - 1
183
208
  # But the numbers are too big, so we'll use openssl
184
209
  x = ciphertext.to_bn.mod_exp(privKey.l, pubKey.n_sq) - 1
@@ -195,8 +220,11 @@ module Paillier
195
220
  # Arguments:
196
221
  # priv: (Paillier::PrivateKey)
197
222
  # pub: (Paillier::PublicKey)
198
- # data: (Int)
223
+ # data: (Int, OpenSSL::BN, String)
199
224
  def self.sign(priv, pub, data)
225
+ if( data.is_a?(String) )
226
+ data = OpenSSL::BN.new(data)
227
+ end
200
228
  hashData = hash(data)
201
229
  # L(u) = (u-1)/n
202
230
  numerators1 = ((hashData.to_bn.mod_exp(priv.l, pub.n_sq) - 1) / pub.n.to_bn)[0]
@@ -225,9 +253,12 @@ module Paillier
225
253
  #
226
254
  # Arguments:
227
255
  # pub: (Paillier::PublicKey)
228
- # message: (Int)
256
+ # message: (Int, OpenSSL::BN, String)
229
257
  # sig: (Paillier::Signature)
230
258
  def self.validSignature?(pub, message, sig)
259
+ if( message.is_a?(String) )
260
+ message = OpenSSL::BN.new(message)
261
+ end
231
262
  hash = Digest::SHA256.hexdigest(message.to_s).to_i(16)
232
263
  # We want to run (g ** s1) * (s2 ** n) % (n**2)
233
264
  # But all those numbers are huge, so we approach it in stages
@@ -6,6 +6,31 @@ module Paillier
6
6
  @l = l
7
7
  @m = m
8
8
  end
9
+
10
+ # Serialize a private key to string form
11
+ #
12
+ # Example:
13
+ # >> priv, pub = Paillier.generateKeypair(2048)
14
+ # >> priv.to_s
15
+ # => "110107191408889682017277609474037601699496910..."
16
+ #
17
+ def to_s
18
+ return "#{@l},#{@m}"
19
+ end
20
+
21
+ # De-serialize a private key string back into object form
22
+ #
23
+ # Example:
24
+ # >> s = priv.to_s
25
+ # >> newPriv = Paillier::PrivateKey.from_s(s)
26
+ # => #<Paillier::PrivateKey>
27
+ #
28
+ # Arguments:
29
+ # string (String)
30
+ def PrivateKey.from_s(string)
31
+ l,m = string.split(",")
32
+ return PrivateKey.new(l.to_i, m.to_i)
33
+ end
9
34
  end
10
35
 
11
36
  class PublicKey
@@ -10,33 +10,37 @@ module Paillier
10
10
  return int.to_s(2).length
11
11
  end
12
12
 
13
- def self.defaultK(bits)
14
- double = bits * 2
15
- return (40 > double) ? 40 : double
16
- end
17
-
18
- # This is based on the Wikipedia article on the Fermat primality test
19
- # returns true if probably prime, false if definitely composite
20
- def self.probabilisticPrimeTest(target, k)
21
- for _ in (1 .. k)
22
- a = rand(2 .. (target-2))
23
- # We want to run "x = (a ** target-1) % target", but the values
24
- # are huge. Instead we call out to openssl and do it with mod_exp
25
- mod = a.to_bn.mod_exp(target-1, target)
26
- if( mod != 1 )
27
- return false # Def composite
28
- end
29
- end
30
- return true # probs prime
31
- end
13
+ # This is an implementation of the Rabin-Miller primality test.
14
+ # Previous versions used Little Fermat, but that is not effective
15
+ # in all cases; specifically, it can be thwarted by Carmichael
16
+ # numbers. We use 50 rounds as the default, in order to get a certainty
17
+ # of 2^-100 that we have found a prime. This implementation is adapted
18
+ # from https://rosettacode.org/wiki/Miller-Rabin_primality_test#Ruby
19
+ def self.probabilisticPrimeTest(target, k=50)
20
+ d = target-1
21
+ s = 0
22
+ while d % 2 == 0
23
+ d /= 2
24
+ s += 1
25
+ end
26
+ k.times do
27
+ a = 2 + rand(target-4)
28
+ x = a.to_bn.mod_exp(d, target)
29
+ next if x == 1 || x == target-1
30
+ (s - 1).times do
31
+ x = x.to_bn.mod_exp(2, target)
32
+ return false if x == 1
33
+ break if x == target - 1
34
+ end
35
+ return false if x != target-1
36
+ end
37
+ return true # probs prime
38
+ end
32
39
 
33
- def self.isProbablyPrime?(possible, k=nil)
40
+ def self.isProbablyPrime?(possible, k=50)
34
41
  if( possible == 1 )
35
42
  return true
36
43
  end
37
- if( k.nil? )
38
- k = defaultK(bitLength(possible))
39
- end
40
44
  for i in SmallPrimes
41
45
  if( possible == i )
42
46
  return true
@@ -59,14 +63,10 @@ module Paillier
59
63
  end
60
64
 
61
65
  # Get a random prime of appropriate length
62
- def self.generatePrime(bits, k=nil)
66
+ def self.generatePrime(bits, k=50)
63
67
  if( bits < 8 )
64
68
  raise "Bits less than eight!"
65
69
  end
66
- if( k == nil )
67
- k = defaultK(bits)
68
- end
69
-
70
70
  while( true )
71
71
  lowerBound = (2 ** (bits-1) + 1)
72
72
  size = ((2 ** bits) - lowerBound)
@@ -82,7 +82,7 @@ module Paillier
82
82
  raise "Bits less than eight!"
83
83
  end
84
84
 
85
- # If we find a number not coprome to n then finding `p` and `q` is trivial.
85
+ # If we find a number not coprime to n then finding `p` and `q` is trivial.
86
86
  # This will almost never happen for keys of reasonable size, so if
87
87
  # `coprime_to` is big enough we won't bother running the expensive test.
88
88
  no_test_needed = false
@@ -0,0 +1,311 @@
1
+
2
+ # needed for bignums
3
+ require 'set'
4
+ require 'openssl'
5
+ require 'securerandom'
6
+ require_relative 'primes'
7
+
8
+ BitStringLength = 256 #:nodoc:
9
+
10
+ module Paillier
11
+
12
+ module ZKP
13
+
14
+ # The ZKP class is used for performing zero-knowledge content proofs.
15
+ # Initialization of a ZKP object generates a commitment that the user can send along with a ciphertext to another party.
16
+ # That party can then use the commitment to confirm that the ciphertext exists in the set of pre-determined valid messages.
17
+ class ZKP
18
+
19
+ # Commitment generated by the ZKP object on initialization, used in ZKPVerify? function
20
+ attr_reader :commitment
21
+
22
+ # Ciphertext generated by the ZKP object; accessible using both myZKP.ciphertext and myZKP.cyphertext
23
+ attr_reader :ciphertext, :cyphertext
24
+
25
+
26
+ # Constructor function for a ZKP object. On initialization, generates a ZKPCommit object for use in verification
27
+ #
28
+ # Example:
29
+ # >> myZKP = Paillier::ZKP::ZKP.new(key, 65, [23, 38, 52, 65, 77, 94])
30
+ # => [#<@p = plaintext>, #<@pubkey = <key>>, #<@ciphertext = <ciphertext>>, #<@cyphertext = <ciphertext>>, #<@commitment = <commitment>>]
31
+ #
32
+ # Arguments:
33
+ # public_key: The key to be used for the encryption (Paillier::PublicKey)
34
+ # plaintext: The message to be encrypted (Integer)
35
+ # valid_messages: The set of valid messages for encryption (Array)
36
+ #
37
+ # NOTE: the order of valid_messages should be the same for both prover and verifier
38
+ def initialize(public_key, plaintext, valid_messages)
39
+ @p = plaintext
40
+ @pubkey = public_key
41
+ @r, @ciphertext = Paillier.rEncrypt(@pubkey, @p)
42
+ @cyphertext = @ciphertext
43
+ @a_s = Array.new()
44
+ @e_s = Array.new()
45
+ @z_s = Array.new()
46
+ @power = nil
47
+ @commitment = nil
48
+
49
+ # we generate a random value omega such that omega is coprime to n
50
+ while( true )
51
+ big_n = BigDecimal( @pubkey.n )
52
+ @omega = Primes.generateCoprime(BigMath.log(big_n, 2).round, @pubkey.n)
53
+ if( @omega > 0 and @omega < @pubkey.n)
54
+ break
55
+ end
56
+ end
57
+
58
+ # a_p = omega ^ n (mod n^2); 'a' calculation for the plaintext
59
+ a_p = @omega.to_bn.mod_exp( @pubkey.n, @pubkey.n_sq)
60
+
61
+ valid_messages.each_with_index do |m_k, k|
62
+ # g_mk = g ^ m_k (mod n^2)
63
+ g_mk = @pubkey.g.to_bn.mod_exp(m_k.to_bn, @pubkey.n_sq)
64
+
65
+ # u_k = c / g_mk (mod n^2)
66
+ # NOTE: this is modular algebra, so u_k = c * invmod(g_mk) (mod n^2)
67
+ u_k = @ciphertext.to_bn.mod_mul(Paillier.modInv(g_mk, @pubkey.n_sq), @pubkey.n_sq)
68
+ unless ( @p == m_k )
69
+ # randomly generate a coprime of n for z_k
70
+ while( true )
71
+ big_n = BigDecimal(@pubkey.n)
72
+ z_k = Primes::generateCoprime(BigMath.log(big_n, 2).round, @pubkey.n)
73
+ if( z_k > 0 and z_k < @pubkey.n )
74
+ break
75
+ end
76
+ end
77
+ @z_s.push(z_k.to_bn)
78
+
79
+ # generate a random e < 2^BitStringLength
80
+ e_k = SecureRandom.random_number((2 ** 256) - 1)
81
+ @e_s.push(e_k.to_bn)
82
+
83
+ # calculate z_k
84
+ # z_nth = z^n (mod n^2)
85
+ z_nth = z_k.to_bn.mod_exp(@pubkey.n, @pubkey.n_sq)
86
+ # u_eth = u^e_k (mod n^2)
87
+ u_eth = u_k.to_bn.mod_exp(e_k.to_bn, @pubkey.n_sq)
88
+ # a_k = z_nth / u_eth (mod n^2) = z_nth * invmod(u_eth) (mod n^2)
89
+ a_k = z_nth.to_bn.mod_mul( Paillier.modInv(u_eth, @pubkey.n_sq), @pubkey.n_sq )
90
+
91
+ @a_s.push(a_k.to_bn)
92
+ else
93
+ @power = k
94
+ @a_s.push(a_p.to_bn)
95
+ end
96
+ end
97
+ # attempting to craft a ZKP object with an invalid message throws exception
98
+ if(@power == nil)
99
+ raise ArgumentError, "Input message does not exist in array of valid messages.", caller
100
+ end
101
+ # we have now generated all a_s, and all e_s and z_s, save for e_p and z_p
102
+ # to generate e_p and z_p, we need to generate the challenge string, hash(a_s)
103
+ # to make the proof non-interactive
104
+ sha256 = OpenSSL::Digest::SHA256.new
105
+ for a_k in @a_s do
106
+ sha256 << a_k.to_s
107
+ end
108
+ challenge_string = sha256.digest.unpack('H*')[0].to_i(16)
109
+
110
+ # now that we have the "challenge string", we calculate e_p and z_p
111
+ e_sum = 0.to_bn
112
+ big_mod = 2.to_bn
113
+ big_mod = big_mod ** 256
114
+ for e_k in @e_s do
115
+ e_sum = (e_sum + e_k).to_bn % big_mod
116
+ end
117
+ # the sum of all e_s must add up to the challenge_string
118
+ e_p = (OpenSSL::BN.new(challenge_string) - e_sum).to_bn % big_mod
119
+ # r_ep = r ^ e_p (mod n)
120
+ r_ep = @r.to_bn.mod_exp(e_p.to_bn, @pubkey.n)
121
+ # z_p = omega * r^e_p (mod n)
122
+ z_p = @omega.to_bn.mod_mul(r_ep.to_bn, @pubkey.n)
123
+
124
+ @e_s.insert(@power, e_p.to_bn)
125
+ @z_s.insert(@power, z_p.to_bn)
126
+ @commitment = ZKPCommit.new(@a_s, @e_s, @z_s)
127
+
128
+ end
129
+ end
130
+
131
+ # Wrapper function that creates a ZKP object for the user.
132
+ # Instead of needing to call Paillier::ZKP::ZKP.new(args), the user calls Paillier::ZKP.new(args).
133
+ #
134
+ # Example:
135
+ # >> myZKP = Paillier::ZKP.new(key, 65, [23, 38, 52, 65, 77, 94])
136
+ # => [#<@p = plaintext>, #<@pubkey = <key>>, #<@ciphertext = <ciphertext>>, #<@cyphertext = <ciphertext>>, #<@commitment = <commitment>>]
137
+ #
138
+ # Arguments:
139
+ # public_key: The key to be used for the encryption (Paillier::PublicKey)
140
+ # plaintext: The message to be encrypted (Integer)
141
+ # valid_messages: The set of valid messages for encryption (Array)
142
+ #
143
+ # NOTE: the order of valid_messages should be the same for both prover and verifier
144
+ def self.new(pubkey, message, valid_messages)
145
+ return Paillier::ZKP::ZKP.new(pubkey, message, valid_messages)
146
+ end
147
+
148
+ # Function that verifies whether a ciphertext is within the set of valid messages.
149
+ #
150
+ # Example:
151
+ #
152
+ # >> Paillier::ZKP.verifyZKP?(key, ciphertext, [23, 38, 65, 77, 94], commitment)
153
+ # => true
154
+ #
155
+ # Arguments:
156
+ # pubkey: The key used for the encryption (Paillier::PublicKey)
157
+ # ciphertext: The ciphertext generated using the public key (OpenSSL::BN)
158
+ # valid_messages: The set of valid messages for encryption (Array)
159
+ # commitment: The commitment generated by the prover (Paillier::ZKP::ZKPCommit)
160
+ #
161
+ # NOTE: the order of valid_messages should be the same for both prover and verifier
162
+ def self.verifyZKP?(pubkey, ciphertext, valid_messages, commitment)
163
+ u_s = Array.new
164
+ for m_k in valid_messages do
165
+ # g_mk = g ^ m_k (mod n^2)
166
+ g_mk = pubkey.g.to_bn.mod_exp(m_k.to_bn, pubkey.n_sq)
167
+ # u_k = c / g_mk (mod n^2) = c * invmod(g_mk) (mod n^2)
168
+ u_k = OpenSSL::BN.new(ciphertext).mod_mul( Paillier.modInv(g_mk, pubkey.n_sq), pubkey.n_sq )
169
+ u_s.push(u_k)
170
+ end
171
+
172
+ # calculate the challenge_string
173
+ sha256 = OpenSSL::Digest::SHA256.new
174
+ for a_k in commitment.a_s do
175
+ sha256 << a_k.to_s
176
+ end
177
+ challenge_string = sha256.digest.unpack('H*')[0].to_i(16)
178
+
179
+ e_sum = 0.to_bn
180
+ big_mod = 2.to_bn
181
+ big_mod = big_mod ** 256
182
+ for e_k in commitment.e_s do
183
+ e_sum = (e_sum + e_k.to_bn) % big_mod
184
+ end
185
+
186
+ # first we check that the sum matches correctly
187
+ unless e_sum == OpenSSL::BN.new(challenge_string)
188
+ return false
189
+ end
190
+ # then we check that z_k^n = a_k * (u_k^e_k) (mod n^2)
191
+ for i in (0 .. (commitment.z_s.size - 1)) do
192
+ a_k = commitment.a_s[i]
193
+ e_k = commitment.e_s[i]
194
+ u_k = u_s[i]
195
+ z_k = commitment.z_s[i]
196
+ # left hand side
197
+ # z_kn = z_k ^ n (mod n^2)
198
+ z_kn = z_k.to_bn.mod_exp(pubkey.n, pubkey.n_sq)
199
+ # right hand side
200
+ # u_ke = u_k ^ e_k (mod n^2)
201
+ u_ke = u_k.to_bn.mod_exp(e_k, pubkey.n_sq)
202
+ # a_kue = a_k * u_ke (mod n^2)
203
+ a_kue = a_k.to_bn.mod_mul(u_ke, pubkey.n_sq)
204
+
205
+ # z_k ^ n ?= a_k * (u_k ^ e_k)
206
+ unless(z_kn == a_kue)
207
+ return false
208
+ end
209
+ end
210
+ # if it passes both tests, then we have validated the contents
211
+ return true
212
+ end
213
+
214
+ # Wrapper class used for containing the components of the ZKP commitment
215
+ class ZKPCommit
216
+
217
+ attr_reader :a_s, :e_s, :z_s #:nodoc:
218
+
219
+ def initialize(a_s, e_s, z_s) # :nodoc:
220
+ @a_s = a_s
221
+ @e_s = e_s
222
+ @z_s = z_s
223
+ end
224
+
225
+ # Serializes a commitment
226
+ #
227
+ # Example:
228
+ #
229
+ # >> myZKP = Paillier::ZKP.new(key, 65, [23, 38, 52, 65, 77, 94])
230
+ # => [#<@p = plaintext>, #<@pubkey = <key>>, #<@ciphertext = <ciphertext>>, #<@cyphertext = <ciphertext>>, #<@commitment = <commitment>>]
231
+ # >> myZKP.commitment.to_s
232
+ # => "<a1>,<a2>,<a3>,<a4>,<a5>,<a6>,;<e1>,<e2>,<e3>,<e4>,<e5>,;<z1>,<z2>,<z3>,<z4>,<z5>,"
233
+ def to_s()
234
+ a_s_string = @a_s.join(',')
235
+ e_s_string = @e_s.join(',')
236
+ z_s_string = @z_s.join(',')
237
+ return "#{a_s_string};#{e_s_string};#{z_s_string}"
238
+ end
239
+
240
+ # Deserializes a commitment
241
+ #
242
+ # Example:
243
+ #
244
+ # >> commit = Paillier::ZKP::ZKPCommit.from_s(commitment_string)
245
+ # => #<Paillier::ZKP::ZKPCommit: @a_s=[<a1>,<a2>, .. ,<an>], @e_s=[<e1>,<e2>, .. ,<en>], @z_s=[<z1>,<z2>, .. ,<zn>]>
246
+ #
247
+ # Arguments:
248
+ # commitment_string: Serialization of a commitment (String)
249
+ def ZKPCommit.from_s(string)
250
+ # these will hold the final result from string-parsing
251
+ a_s = Array.new
252
+ e_s = Array.new
253
+ z_s = Array.new
254
+
255
+ # separate at the semicolons
256
+ a_s_string, e_s_string, z_s_string = string.split(";")
257
+
258
+ # separate at the commas
259
+ a_s_strings = a_s_string.split(",")
260
+ e_s_strings = e_s_string.split(",")
261
+ z_s_strings = z_s_string.split(",")
262
+
263
+ # convert into arrays of bignums
264
+ for a in a_s_strings do
265
+ a_s.push(OpenSSL::BN.new(a))
266
+ end
267
+ for e in e_s_strings do
268
+ e_s.push(OpenSSL::BN.new(e))
269
+ end
270
+ for z in z_s_strings do
271
+ z_s.push(OpenSSL::BN.new(z))
272
+ end
273
+
274
+ # create the object with these arrays
275
+ return ZKPCommit.new(a_s, e_s, z_s)
276
+ end
277
+
278
+ # == operator overload to compare two ZKP commit objects
279
+ def ==(y) #:nodoc:
280
+ # if the array sizes don't match return false
281
+ if @a_s.size != y.a_s.size
282
+ return false
283
+ end
284
+ if @e_s.size != y.e_s.size
285
+ return false
286
+ end
287
+ if @z_s.size != y.z_s.size
288
+ return false
289
+ end
290
+ # if the corresponding elements in the arrays don't math return false
291
+ for i in (0 .. (@a_s.size - 1)) do
292
+ if(@a_s[i] != y.a_s[i])
293
+ return false
294
+ end
295
+ end
296
+ for i in (0 .. (@e_s.size - 1)) do
297
+ if(@e_s[i] != y.e_s[i])
298
+ return false
299
+ end
300
+ end
301
+ for i in (0 .. (@z_s.size - 1)) do
302
+ if(@z_s[i] != y.z_s[i])
303
+ return false
304
+ end
305
+ end
306
+ # else return true
307
+ return true
308
+ end
309
+ end
310
+ end
311
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paillier
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daylighting Society
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-18 00:00:00.000000000 Z
11
+ date: 2018-11-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: An implementation of Paillier homomorphic addition public key system
14
14
  email: paillier@daylightingsociety.org
@@ -20,6 +20,7 @@ files:
20
20
  - lib/paillier/keys.rb
21
21
  - lib/paillier/primes.rb
22
22
  - lib/paillier/signatures.rb
23
+ - lib/paillier/zkp.rb
23
24
  homepage: https://paillier.daylightingsociety.org
24
25
  licenses:
25
26
  - LGPL-3.0
@@ -39,8 +40,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
39
40
  - !ruby/object:Gem::Version
40
41
  version: '0'
41
42
  requirements: []
42
- rubyforge_project:
43
- rubygems_version: 2.6.4
43
+ rubygems_version: 3.0.3
44
44
  signing_key:
45
45
  specification_version: 4
46
46
  summary: Paillier Homomorphic Cryptosystem