def client(self, index: int) -> str: """ Args: index: int, which index the client want to get from server's input list. Returns: str, message """ param_s = self.var_chan.recv(tag='ot_param_s') x = self.secrets_generator.randint(1, P-1) param_r = add(multiply(param_s, int(index)), multiply(G, x)) self.var_chan.send(param_r, tag='ot_param_r') key_pub = multiply(param_s, x) key = hashlib.sha256(str(int("04" + "%064x" % key_pub[0] + "%064x" % key_pub[1], 16)).encode('utf-8')).digest() recv_msg_list = self.var_chan.recv(tag='ot_encrypted_messages') if not (0 <= index <= self.n - 1): raise ValueError(f"Index {index} is supposed to be a number between 1 and n.") recv_msg = base64.b64decode(recv_msg_list[index]) iv = recv_msg[:AES.block_size] cipher = recv_msg[AES.block_size:] aes = AES.new(key, AES.MODE_CBC, iv) decrypted_message = self._unpad(aes.decrypt(cipher)).decode('utf-8') return decrypted_message
def server(self, msg_list: List[str]) -> None: """ Args: msg_list: list, list consist of string. Returns: None """ y = self.secrets_generator.randint(1, P-1) param_s = multiply(G, y) self.var_chan.send(param_s, tag='ot_param_s') param_r = self.var_chan.recv(tag='ot_param_r') encrypted_msg_list = [] iv = Random.new().read(AES.block_size) for i, msg in enumerate(msg_list): key_pub = multiply(add(param_r, multiply(param_s, (-1) * i)), y) key = hashlib.sha256( str(int("04" + "%064x" % key_pub[0] + "%064x" % key_pub[1], 16)).encode('utf-8')).digest() aes = AES.new(key, AES.MODE_CBC, iv) cipher = aes.encrypt(self._pad(msg).encode()) encrypted_msg_list.append(base64.b64encode(iv + cipher)) self.var_chan.send(encrypted_msg_list, tag='ot_encrypted_messages') return
def encrypt(message: bytes, enckey: (int, int)) -> bytes: # This is an implementation of ECIES # https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme util.validate_curve_point(enckey) r = util.random_private_value() R = secp256k1.multiply(secp256k1.G, r) S = secp256k1.multiply(enckey, r) kEkM = sha3.keccak_256(S[0].to_bytes(32, byteorder='big')).digest() kE, kM = kEkM[0:16], kEkM[16:32] # Use CTR mode to do encryption 256 bits at a time # https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CTR num_trunc_bytes = (32 - len(message)) % 32 iv = util.random.randrange(2**256).to_bytes(32, byteorder='big') num_chunks = len(message) // 32 + (1 if num_trunc_bytes > 0 else 0) c = b''.join( (int.from_bytes(message[32 * i:32 * (i + 1)].ljust(32, b'\0'), 'big') ^ int.from_bytes( sha3.keccak_256(kE + iv + i.to_bytes(32, 'big')).digest(), 'big') ).to_bytes(32, byteorder='big') for i in range(num_chunks)) # Quote from http://keccak.noekeon.org/: # Unlike SHA-1 and SHA-2, Keccak does not have the length-extension weakness, # hence does not need the HMAC nested construction. Instead, MAC computation # can be performed by simply prepending the message with the key. d = sha3.keccak_256(kM + c).digest() return (util.curve_point_to_bytes(R) + # 64 byte ephemeral key bytes((num_trunc_bytes, )) + # 1 byte truncation descriptor iv + # 32 byte initialization vector c + # arbitrary length 32 byte aligned enciphered message d) # 32 byte message authentication code (MAC)
def generateZKP(self, preSecrets, shares): vArr = [] wArr = [] n = len(preSecrets) toBeHashed = bytes('') for i in range(n): sh = shares[i] v = ec.multiply(self.generatorSecondary, preSecrets[i]) vArr.append(v) w = self.sample(self.order) wArr.append(w) (a1, a2) = (ec.multiply(self.publicKeys[i], w), ec.multiply(self.generatorSecondary, w)) arr = [sh[0], sh[1], v[0], v[1], a1[0], a1[1], a2[0], a2[1]] for ele in arr: toBeHashed += encode_int32(ele) e = sha3(toBeHashed) e = mpz(codecs.encode(str(e), 'hex'), 16) zArr = [ long(gmpy2.f_mod(wArr[i] - preSecrets[i] * e, self.order)) for i in range(n) ] e = long(e) return [vArr, e, zArr]
def process_encryption_key_vector(self, sender_address: int, encryption_key_vector: tuple, signature: 'rsv triplet'): own_address = self.node.address participant = self.get_participant_by_address(sender_address) msg_bytes = ( b'ENCRYPTIONKEYPART' + self.decryption_condition.encode() + util.curve_point_tuple_to_bytes(encryption_key_vector) ) recovered_address = util.address_from_message_and_signature(msg_bytes, signature) if sender_address != recovered_address: raise ValueError( 'sender address {:040x} does not match recovered address {:040x}' .format(sender_address, recovered_address) ) if participant.encryption_key_vector is None: lhs = secp256k1.multiply(secp256k1.G, participant.secret_share1) rhs = functools.reduce( secp256k1.add, (secp256k1.multiply(ps, pow(own_address, k, secp256k1.N)) for k, ps in enumerate(encryption_key_vector))) if lhs != rhs: participant.get_or_create_complaint_by_complainer_address(own_address) raise ValueError( '{:040x} sent enc key vector which does not match previously sent secret share' .format(sender_address) ) participant.encryption_key_vector = encryption_key_vector participant.encryption_key_vector_signature = signature if all(p.encryption_key_vector is not None for p in self.participants): self.encryption_key = functools.reduce( secp256k1.add, (p.encryption_key_vector[0] for p in self.participants), self.encryption_key_vector[0] ) db.Session.commit() elif participant.encryption_key_vector != encryption_key_vector: participant.get_or_create_complaint_by_complainer_address(own_address) raise ValueError( '{:040x} sent encryption key part for {} which do not match: {} != {}' .format( sender_address, self.decryption_condition, participant.encryption_key_vector, encryption_key_vector, ) )
def encrypt(pubkey, plaintext_bytes): padded = pad(plaintext_bytes, AES.block_size) r = random.SystemRandom().randrange(1, secp256k1.N) R = secp256k1.multiply(secp256k1.G, r) R_bytes = encode_point(R) S = secp256k1.multiply(decode_point(pubkey), r)[0] key_enc = ethereum.utils.sha3(ethereum.utils.int_to_bytes(S + 1)) prefix_bytes = random.getrandbits(64).to_bytes(8, byteorder='big') ctr = Counter.new(64, prefix=prefix_bytes) cipher = AES.new(key=key_enc, mode=AES.MODE_CTR, counter=ctr) ciphertext = cipher.encrypt(padded) return rlp.encode([R_bytes, prefix_bytes, ciphertext])
def decrypt(ciphertext: bytes, deckey: int, foo=False) -> bytes: util.validate_private_value(deckey) R = util.bytes_to_curve_point(ciphertext[:64]) S = secp256k1.multiply(R, deckey) num_trunc_bytes = ord(ciphertext[64:65]) iv = ciphertext[65:97] c = ciphertext[97:-32] if len(c) % 32 != 0: raise ValueError('enciphered message not properly aligned') kEkM = sha3.keccak_256(S[0].to_bytes(32, byteorder='big')).digest() kE, kM = kEkM[0:16], kEkM[16:32] num_chunks = len(c) // 32 message = b''.join( (int.from_bytes(c[32 * i:32 * (i + 1)], 'big') ^ int.from_bytes( sha3.keccak_256(kE + iv + i.to_bytes(32, 'big')).digest(), 'big') ).to_bytes(32, byteorder='big') for i in range(num_chunks)) if num_trunc_bytes > 0: message, padding = message[:-num_trunc_bytes], message[ -num_trunc_bytes:] if padding != b'\0' * num_trunc_bytes: raise ValueError('invalid padding') d = ciphertext[-32:] if d != sha3.keccak_256(kM + c).digest(): raise ValueError('message authentication code does not match') if foo: return int.from_bytes(sha3.keccak_256(message).digest(), 'big') return message
def decrypt(privkey, encrypted_bytes): R_bytes, prefix_bytes, ciphertext = rlp.decode(encrypted_bytes) S = secp256k1.multiply(decode_point(R_bytes), privkey)[0] key_enc = ethereum.utils.sha3(ethereum.utils.int_to_bytes(S + 1)) ctr = Counter.new(64, prefix=prefix_bytes) cipher = AES.new(key=key_enc, mode=AES.MODE_CTR, counter=ctr) plaintext = cipher.decrypt(ciphertext) return unpad(plaintext, AES.block_size)
def generate1ZKP(self, ex, gen1, gen2): sh = ec.multiply(gen1, ex) v = ec.multiply(gen2, ex) w = self.sample(self.order) (a1, a2) = (ec.multiply(gen1, w), ec.multiply(gen2, w)) print 'As : ' print[a1[0], a1[1], a2[0], a2[1]] arr = [sh[0], sh[1], v[0], v[1], a1[0], a1[1], a2[0], a2[1]] toBeHashed = bytes('') for ele in arr: toBeHashed += encode_int32(ele) e = sha3(toBeHashed) e = mpz(codecs.encode(str(e), 'hex'), 16) z = long(gmpy2.f_mod(w - ex * e, self.order)) e = long(e) return [v, sh, e, z]
def process_secret_share_verification(self, address: int): own_address = self.node.address participant = self.get_participant_by_address(address) share1 = participant.secret_share1 share2 = participant.secret_share2 vlhs = secp256k1.add(secp256k1.multiply(secp256k1.G, share1), secp256k1.multiply(G2, share2)) vrhs = functools.reduce( secp256k1.add, (secp256k1.multiply(ps, pow(own_address, k, secp256k1.N)) for k, ps in enumerate(participant.verification_points))) if vlhs == vrhs: return participant.get_or_create_complaint_by_complainer_address(own_address)
def verify1ZKP(self, proof, gen1, gen2, verbal): #print proof v, sh, e, z = proof if verbal: print "Verifying ZKP..." if verbal: print "e = " + str(e) + "\nIntermediates" a1 = ec.add(ec.multiply(gen1, z), ec.multiply(sh, e)) a2 = ec.add(ec.multiply(gen2, z), ec.multiply(v, e)) if verbal: print conc([str(ele) for ele in [a1[0], a1[1], a2[0], a2[1]]]) arr = [sh[0], sh[1], v[0], v[1], a1[0], a1[1], a2[0], a2[1]] toBeHashed = bytes('') for ele in arr: toBeHashed += encode_int32(ele) eVerify = sha3(toBeHashed) e = encode_int32(e) if verbal: print "Recovered e : " + mpz(codecs.encode(eVerify, 'hex'), 16).digits() return eVerify == e
def CreateStealthTx(pub_scan_key, pub_spend_key): from random import SystemRandom rnd = SystemRandom() r = rnd.getrandbits(256) R = CompressPoint(curve.multiply(curve.G, r)) ss = GetSharedSecret(pub_scan_key, r) addr = GetAddrFromSharedSecret(ss, pub_spend_key) R = hex(int.from_bytes(R, 'big')) addr = hex(int.from_bytes(addr, 'big')) return R, addr
def init(self): for addr in networking.channels.keys(): self.get_or_create_participant_by_address(addr) # everyone should on agree on participants self.threshold = math.ceil(THRESHOLD_FACTOR * (len(self.participants)+1)) spoly1 = random_polynomial(self.threshold) spoly2 = random_polynomial(self.threshold) self.secret_poly1 = spoly1 self.secret_poly2 = spoly2 self.encryption_key_vector = tuple(secp256k1.multiply(secp256k1.G, coeff) for coeff in self.secret_poly1) self.verification_points = tuple( secp256k1.add(secp256k1.multiply(secp256k1.G, a), secp256k1.multiply(G2, b)) for a, b in zip(spoly1, spoly2) ) self.phase = ECDKGPhase.key_distribution
def GetSharedSecret(R, scan_key): from hashlib import sha256 if type(scan_key) == bytes: scan_key = int.from_bytes(scan_key, 'big') SS = curve.multiply(R, scan_key) hasher = sha256() hasher.update(int.to_bytes(SS[0], 32, 'big') + int.to_bytes(SS[1], 32, 'big')) ss = hasher.digest() return ss
def PVSSDistribute(self, s): publicKeys = self.publicKeys s = long(s) n = self.n t = self.t secret = ec.multiply(self.generatorPrimary, s) print "Secret : " + tostr(secret) poly = [self.sample(self.order) for i in range(t - 1)] poly.append(s) preSecrets = [] shares = [] for i in range(1, n + 1): temp = long(self.evaluatePoly(poly, i, self.order)) preSecrets.append(temp) temp = ec.multiply(publicKeys[i - 1], temp) shares.append(temp) proof = self.generateZKP(preSecrets, shares) print "Polynomial Coefficients : " + tostr(poly) print "Evaluations: " + tostr(preSecrets) print "...Shares: " + conc([tostr(s) for s in shares]) return shares, proof
def verifyZKP(self, shares, vArr, e, zArr, verbal): if verbal: print "\nVerification..." self.verifyByCode(vArr, verbal) n = len(shares) if verbal: print "\ne = " + str(e) + "\nIntermediates" toBeHashed = bytes('') for i in range(n): sh = shares[i] v = vArr[i] (a1,a2) = (ec.add(ec.multiply(self.publicKeys[i],zArr[i]),ec.multiply(shares[i],e)),\ ec.add(ec.multiply(self.generatorSecondary,zArr[i]),ec.multiply(vArr[i],e))) if verbal: print conc([str(ele) for ele in [a1[0], a1[1], a2[0], a2[1]]]) arr = [sh[0], sh[1], v[0], v[1], a1[0], a1[1], a2[0], a2[1]] for ele in arr: toBeHashed += encode_int32(ele) eVerify = sha3(toBeHashed) e = encode_int32(e) if verbal: print "Recovered e : " + mpz(codecs.encode(eVerify, 'hex'), 16).digits() #if verbal : print codecs.encode(str(e),'hex') return eVerify == e
def process_decryption_key_part(self, sender_address: int, decryption_key_part: int, signature: 'rsv triplet'): participant = self.get_participant_by_address(sender_address) msg_bytes = ( b'DECRYPTIONKEYPART' + self.decryption_condition.encode() + util.private_value_to_bytes(decryption_key_part) ) recovered_address = util.address_from_message_and_signature(msg_bytes, signature) if sender_address != recovered_address: raise ValueError( 'sender address {:040x} does not match recovered address {:040x}' .format(sender_address, recovered_address) ) if participant.decryption_key_part is None: if secp256k1.multiply(secp256k1.G, decryption_key_part) != participant.encryption_key_vector[0]: participant.get_or_create_complaint_by_complainer_address(own_address) raise ValueError( '{:040x} sent dec key part which does not match previously sent enc key vector' .format(sender_address) ) participant.decryption_key_part = decryption_key_part participant.decryption_key_part_signature = signature if all(p.decryption_key_part is not None for p in self.participants): self.decryption_key = ( sum(p.decryption_key_part for p in self.participants) + self.secret_poly1[0] ) % secp256k1.N db.Session.commit() elif participant.decryption_key_part != decryption_key_part: participant.get_or_create_complaint_by_complainer_address(own_address) raise ValueError( '{:040x} sent decryption key part for {} which do not match: {} != {}' .format( sender_address, self.decryption_condition, participant.decryption_key_part, decryption_key_part, ) )
def PVSSReconstruct(self, xl, dSecrets): t = self.t result = (0, 0) for x, d in zip(xl, dSecrets): lambnum = 1 lambden = 1 for otherx in xl: if not otherx == x: lambnum *= otherx lambden *= otherx - x lamb = lambnum * gmpy2.invert(lambden, self.order) lamb = gmpy2.f_mod(lamb, self.order) print "Lambda (" + str(x) + ") : " + str(lamb) temp = ec.multiply(d, long(lamb)) result = ec.add(result, temp) return result
def test_can_decrypt_encrypted_random_messages(chain): # TODO: Fix populus compat ies, _ = chain.provider.get_or_deploy_contract( 'IntegratedEncryptionScheme') num_runs = 10 average_gas_cost = 0 for _ in range(num_runs): message = os.urandom(util.random.randrange(1, 100)) deckey = util.random_private_value() enckey = secp256k1.multiply(secp256k1.G, deckey) ciphertext = crypto.encrypt(message, enckey) assert message == crypto.decrypt(ciphertext, deckey) assert crypto.decrypt(ciphertext, deckey, foo=True) == ies.call().decrypt( ciphertext, deckey) average_gas_cost += ies.estimateGas().decrypt(ciphertext, deckey) average_gas_cost /= num_runs
def verifyByCode(self, vArr, verbal): randomVec = [ int(gmpy2.mpz_random(self.rs, self.order)) for i in range(self.n - self.t) ] codewordInDual = self.code.getCodewordInDual(randomVec) codewordInDual = [ gmpy2.f_mod(mpz(int(ele)), self.order) for ele in codewordInDual ] if verbal: print "Random codeword from dual : " + tostr(codewordInDual) if verbal: print "Intermediates" product = (0L, 0L) for vi, ci in zip(vArr, codewordInDual): temp = ec.multiply(vi, ci) if verbal: print str(ci) + " x " + tostr(vi) + " = " + tostr(temp) product = ec.add(product, temp) if verbal: print "Product : " + tostr(product) if product == (0L, 0L): if verbal: print "...Codeword valid : v"
def test_nodes_match_enckey_and_deckeys(nodes, request_timeout): wait_for_all_nodes_connected(nodes, request_timeout) deccond = 'past {}'.format(datetime.utcnow().isoformat()) enckeys = [ requests.post('http://localhost:{}'.format(n.port), verify=False, timeout=request_timeout, data=json.dumps({ 'id': 'honk', 'method': 'get_encryption_key', 'params': [deccond], })).json()['result'] for n in nodes ] enckeys = [tuple(int(ek[i:i + 64], 16) for i in (0, 64)) for ek in enckeys] for ek in enckeys: util.validate_curve_point(ek) assert (all(ek == enckeys[0] for ek in enckeys[1:])) deckeys = [ requests.post('http://localhost:{}'.format(n.port), verify=False, timeout=request_timeout, data=json.dumps({ 'id': 'honk', 'method': 'get_decryption_key', 'params': [deccond], })).json()['result'] for n in nodes ] deckeys = [int(dk, 16) for dk in deckeys] for dk in deckeys: util.validate_private_value(dk) assert (all(dk == deckeys[0] for dk in deckeys[1:])) assert (secp256k1.multiply(secp256k1.G, deckeys[0]) == enckeys[0])
def private_value_to_eth_address(private_value: int) -> int: return curve_point_to_eth_address(secp256k1.multiply(secp256k1.G, private_value))
def generate_public_shares(poly1, poly2): if len(poly1) != len(poly2): raise ValueError('polynomial lengths must match ({} != {})'.format(len(poly1), len(poly2))) return (secp256k1.add(secp256k1.multiply(secp256k1.G, a), secp256k1.multiply(G2, b)) for a, b in zip(poly1, poly2))
import sys from random import randint from py_ecc.secp256k1.secp256k1 import add, multiply, inv, N, P, G from .utils import hashs #assert False == "Do not use, use altbn128" safe_ord = ord if sys.version_info.major == 2 else lambda x: x if isinstance( x, int) else ord(x) bytes_to_int = lambda x: reduce(lambda o, b: (o << 8) + safe_ord(b), [0] + list(x)) hashsn = lambda *x: hashs(*x) % N hashpn = lambda *x: hashsn(*[item for sublist in x for item in sublist]) randsn = lambda: randint(1, N - 1) sbmul = lambda s: multiply(G, s) invmulp = lambda x, y: (x * pow(y, P - 2, P)) invmodn = lambda x: inv(x, N) addmodn = lambda x, y: (x + y) % N mulmodn = lambda x, y: (x * y) % N submodn = lambda x, y: (x - y) % N negp = lambda x: (x[0], -x[1])
def public_key(self): return secp256k1.multiply(secp256k1.G, self.private_key)
def generateKeyPair(self): secretKey = self.sample(self.order - 1) + 1 publicKey = ec.multiply(self.generatorPrimary, secretKey) return [secretKey, publicKey]
def GetAddrFromSharedSecret(ss, pub_spend_key): P = curve.multiply(curve.G, int.from_bytes(ss, 'big')) P = curve.add(P, pub_spend_key) addr = GetAddrFromPubKey(P) return addr
def decryptShare(self, share, secretKey): secretKey = mpz(secretKey) inv = long(gmpy2.invert(secretKey, self.order)) result = ec.multiply(share, inv) return result