paillier 1.0.0 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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