Module: Paillier::ZKP
- Defined in:
- lib/paillier/zkp.rb
Defined Under Namespace
Class Method Summary collapse
-
.new(pubkey, message, valid_messages) ⇒ Object
Wrapper function that creates a ZKP object for the user.
-
.verifyZKP?(pubkey, ciphertext, valid_messages, commitment) ⇒ Boolean
Function that verifies whether a ciphertext is within the set of valid messages.
Class Method Details
.new(pubkey, message, valid_messages) ⇒ Object
Wrapper function that creates a ZKP object for the user. Instead of needing to call Paillier::ZKP::ZKP.new(args), the user calls Paillier::ZKP.new(args).
Example: >> myZKP = Paillier::ZKP.new(key, 65, [23, 38, 52, 65, 77, 94]) => [#<@p = plaintext>, #<@pubkey = <key>>, #<@ciphertext = <ciphertext>>, #<@cyphertext = <ciphertext>>, #<@commitment = <commitment>>]
Arguments: public_key: The key to be used for the encryption (Paillier::PublicKey) plaintext: The message to be encrypted (Integer) valid_messages: The set of valid messages for encryption (Array)
NOTE: the order of valid_messages should be the same for both prover and verifier
144 145 146 |
# File 'lib/paillier/zkp.rb', line 144 def self.new(pubkey, , ) return Paillier::ZKP::ZKP.new(pubkey, , ) end |
.verifyZKP?(pubkey, ciphertext, valid_messages, commitment) ⇒ Boolean
Function that verifies whether a ciphertext is within the set of valid messages.
Example:
>> Paillier::ZKP.verifyZKP?(key, ciphertext, [23, 38, 65, 77, 94], commitment) => true
Arguments: pubkey: The key used for the encryption (Paillier::PublicKey) ciphertext: The ciphertext generated using the public key (OpenSSL::BN) valid_messages: The set of valid messages for encryption (Array) commitment: The commitment generated by the prover (Paillier::ZKP::ZKPCommit)
NOTE: the order of valid_messages should be the same for both prover and verifier
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/paillier/zkp.rb', line 162 def self.verifyZKP?(pubkey, ciphertext, , commitment) u_s = Array.new for m_k in do # g_mk = g ^ m_k (mod n^2) g_mk = pubkey.g.to_bn.mod_exp(m_k.to_bn, pubkey.n_sq) # u_k = c / g_mk (mod n^2) = c * invmod(g_mk) (mod n^2) u_k = OpenSSL::BN.new(ciphertext).mod_mul( Paillier.modInv(g_mk, pubkey.n_sq), pubkey.n_sq ) u_s.push(u_k) end # calculate the challenge_string sha256 = OpenSSL::Digest::SHA256.new for a_k in commitment.a_s do sha256 << a_k.to_s end challenge_string = sha256.digest.unpack('H*')[0].to_i(16) e_sum = 0.to_bn big_mod = 2.to_bn big_mod = big_mod ** 256 for e_k in commitment.e_s do e_sum = (e_sum + e_k.to_bn) % big_mod end # first we check that the sum matches correctly unless e_sum == OpenSSL::BN.new(challenge_string) return false end # then we check that z_k^n = a_k * (u_k^e_k) (mod n^2) for i in (0 .. (commitment.z_s.size - 1)) do a_k = commitment.a_s[i] e_k = commitment.e_s[i] u_k = u_s[i] z_k = commitment.z_s[i] # left hand side # z_kn = z_k ^ n (mod n^2) z_kn = z_k.to_bn.mod_exp(pubkey.n, pubkey.n_sq) # right hand side # u_ke = u_k ^ e_k (mod n^2) u_ke = u_k.to_bn.mod_exp(e_k, pubkey.n_sq) # a_kue = a_k * u_ke (mod n^2) a_kue = a_k.to_bn.mod_mul(u_ke, pubkey.n_sq) # z_k ^ n ?= a_k * (u_k ^ e_k) unless(z_kn == a_kue) return false end end # if it passes both tests, then we have validated the contents return true end |