def verifiy_ASNL(P1, P2, L1, s2, s): """ :param P1: public key 1, from_string format (32bytes) :param P2: public key 2, from_string format (32bytes) :param L1: vector of public key (to_string format, 32bytes) :param s2: vector of 32 bytes number :param s: 32 bytes number, aggregate of s1 :return: """ n = len(P1) LHS = to_32_bytes_number(0) RHS = g.from_string(s, curve=crv).verifying_key.pubkey.point for j in range(0, n): c2 = hashlib.sha256(L1[j]).digest() L2Point = g.from_string(s2[j], curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P2[j], curve=crv).pubkey.point * to_int_from_bytes(c2) ) L2 = VerifyingKey.from_public_point(L2Point, curve=crv).to_string() if j == 0: LHS = VerifyingKey.from_string(L1[j], curve=crv).pubkey.point else: LHS = LHS + VerifyingKey.from_string(L1[j], curve=crv).pubkey.point c1 = hashlib.sha256(L2).digest() RHS = RHS + ( VerifyingKey.from_string(P1[j], curve=crv).pubkey.point * to_int_from_bytes(c1) ) assert ( VerifyingKey.from_public_point(LHS, curve=crv).to_string() == VerifyingKey.from_public_point(RHS, curve=crv).to_string() ), "generate_ASNL failed to generate a valid signature.\nAborting..."
def ecdh_encode(mask, amount, receiver_public_key): """ This function encode the a number (the amount) so that it can only be decoded with the receiver private key. Amount is however only masked, calculation can still be applied on it. :param mask: the mask to hide (32 bytes number) :param amount: the amount to hide (32 bytes number) :param receiver_public_key: the receiver public key (sec format) :return: a triplet of new_mask: hidden mask (32 bytes number) new_amount: hidden amount (32 bytes number) sender_public_key: the public key generated by the sender to encode this amount (sec format) """ secret = to_32_bytes_number(random.randrange(crv.order)) sender_secret_key = g.from_string(secret, curve=crv) sender_public_key = sender_secret_key.verifying_key recv_public_key = VerifyingKey.from_string(receiver_public_key, curve=crv) to_hash = VerifyingKey.from_public_point( recv_public_key.pubkey.point * to_int_from_bytes(secret), curve=crv ).to_string() shared_secret_int = to_int_from_bytes(hashlib.sha256(to_hash).digest()) new_mask = (to_int_from_bytes(mask) + shared_secret_int) % crv.order new_amount = (to_int_from_bytes(amount) + shared_secret_int) % crv.order return ( to_32_bytes_number(new_mask), to_32_bytes_number(new_amount), sender_public_key.tpo_string(), )
def verify_schnorr_non_linkable(P1, P2, L1, s1, s2): # P1: Pubkey in from_string format (32 bytes) # P2: Pubkey in from_string format (32 bytes) # L1: output of GenSchnorr, pubkey in from_string format (32 bytes) # s1: output of GenSchnorr, number (32 bytes) # s2: output of GenSchnorr, number (32 bytes) L1Point = VerifyingKey.from_string(L1, curve=crv).pubkey.point c2 = hashlib.sha256( to_32_bytes_number(L1Point.x()) + to_32_bytes_number(L1Point.y()) ).digest() L2PointA = g.from_string(s2, curve=crv).verifying_key.pubkey.point L2Point = g.from_string(s2, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P2, curve=crv).pubkey.point * to_int_from_bytes(c2) ) c1 = hashlib.sha256( to_32_bytes_number(L2Point.x()) + to_32_bytes_number(L2Point.y()) ).digest() L1p = VerifyingKey.from_public_point( g.from_string(s1, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P1, curve=crv).pubkey.point * to_int_from_bytes(c1) ), curve=crv, ).to_string() assert ( L1 == L1p ), "generate_schnorr_non_linkable failed to generate a valid signature.\nAborting..."
def from_point(cls, point, network=BitcoinMainNet, **kwargs): """Create a PublicKey from a point on the SECP256k1 curve. :param point: A point on the SECP256k1 curve. :type point: SECP256k1.point """ verifying_key = VerifyingKey.from_public_point(point, curve=SECP256k1) return cls.from_verifying_key(verifying_key, network=network, **kwargs)
def verify(self, to_be_signed: bytes, signature: bytes, alg: Optional[CoseAlgorithms] = None, curve: Optional[EllipticCurveType] = None) -> bool: """ Verifies the digital signature over 'to_be_signed'. The parameter 'alg' and 'curve' parameters are optional in case they are already provided by one of the COSE key objects. :param to_be_signed: data that was signed :param signature: signature to verify :param alg: an optional algorithm parameter (specifies the exact algorithm used for the signature). :param curve: an optional curve """ self._check_key_conf(algorithm=alg, key_operation=KeyOps.VERIFY, curve=curve) try: alg_cfg = config(CoseAlgorithms(self.alg)) except KeyError as err: raise CoseInvalidAlgorithm(err) p = Point(curve=alg_cfg.curve.curve, x=int(hexlify(self.x), 16), y=int(hexlify(self.y), 16)) vk = VerifyingKey.from_public_point(p, alg_cfg.curve, alg_cfg.hash, validate_point=True) return vk.verify(signature, to_be_signed)
def from_sec(string, curve=curves.SECP256k1, hashfunc=sha1, validate_point=True): """Convert a public key in SEC binary format to a verifying key.""" # based on code from https://github.com/richardkiss/pycoin if string.startswith(b('\x04')): # uncompressed return VerifyingKey.from_string(string[1:], curve, hashfunc, validate_point) elif string.startswith(b('\x02')) or string.startswith(b('\x03')): # compressed is_even = string.startswith(b('\x02')) x = string_to_number(string[1:]) order = curve.order p = curve.curve.p() alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if validate_point: assert ecdsa.point_is_valid(curve.generator, x, y) point = ellipticcurve.Point(curve.curve, x, y, order) return VerifyingKey.from_public_point(point, curve, hashfunc)
def get_ecdsa_verifying_key(pub): #some shenanigans required to validate a transaction sig; see #python.ecdsa PR #54. This will be a lot simpler when that's merged. #https://github.com/warner/python-ecdsa/pull/54/files if not pub[0] in ["\x02", "\x03"]: log.debug("Invalid pubkey") return None is_even = pub.startswith('\x02') x = string_to_number(pub[1:]) order = SECP256k1.order p = SECP256k1.curve.p() alpha = (pow(x, 3, p) + (SECP256k1.curve.a() * x) + SECP256k1.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if not point_is_valid(SECP256k1.generator, x, y): return None point = Point(SECP256k1.curve, x, y, order) return VerifyingKey.from_public_point(point, SECP256k1, hashfunc=hashlib.sha256)
def from_parent(parent_key, i): if i & HARDENED_INDEX: raise ValueError( "Can't generate a hardened child key from a parent public key." ) child = hmac.new( parent_key.chain_code, parent_key.compressed_key + i.to_bytes(length=4, byteorder='big'), hashlib.sha512).digest() child_left, child_right = child[:32], child[32:] if int.from_bytes(child_left, 'big') >= ecdsa.generator_256.order(): return None temp_pri_key = SigningKey.from_string(string=child_left, curve=curves.NIST256p) ki = temp_pri_key.verifying_key.pubkey.point + parent_key.key.pubkey.point if ki == ellipticcurve.INFINITY: return None return HDPublicKey(public_key=VerifyingKey.from_public_point( point=ki, curve=curves.NIST256p), chain_code=child_right, index=i, depth=parent_key.depth + 1, parent_fingerprint=parent_key.fingerprint)
def derive(self, path="m"): tokens = path.split('/') if tokens[0] == "m": k = self.m c = self.c for r in tokens[1:]: if not rformat.match(r): raise self.path_error if r[-1] == "'": i = iH(int(r[:-1])) else: i = int(r) k, c = ckd_prv(k, c, i) return SigningKey.from_string(k.to_bytes(32, byteorder='big'), curve=SECP256k1) elif tokens[0] == "M": K = self.M c = self.c for r in tokens[1:]: if not rformat.match(r): raise self.path_error if r[-1] == "'": i = iH(int(r[:-1])) else: i = int(r) K, c = ckd_pub(K, c, i) return VerifyingKey.from_public_point(K, curve=SECP256k1) else: raise self.path_error
def create_material(self, bits, d=None, x=None, y=None): curve = self.curve_for_bits(bits) if d: return SigningKey.from_secret_exponent(d, curve) if x and y: point = ec.Point(curve.curve, x, y, curve.order) return VerifyingKey.from_public_point(point, curve)
def from_point(cls, point, network=BitcoinMainNet, **kwargs): """Create a PublicKey from a point on the SECP256k1 curve. :param point: A point on the SECP256k1 curve. :type point: SECP256k1.point """ verifying_key = VerifyingKey.from_public_point(point, curve=SECP256k1) return cls.from_verifying_key(verifying_key, network=network, **kwargs)
def vk_from_point(x: bytes, y: bytes): curve = ecdsa_curves.NIST256p x = int(x.hex(), 16) y = int(y.hex(), 16) p = ellipticcurve.Point(curve.curve, x, y) key = VerifyingKey.from_public_point(p, curve) return key
def _CKD_pub(cK, c, s): order = generator_secp256k1.order() I = hmac.new(c, cK + s, hashlib.sha512).digest() curve = SECP256k1 pubkey_point = string_to_number( I[0:32]) * curve.generator + ser_to_point(cK) public_key = VerifyingKey.from_public_point(pubkey_point, curve=SECP256k1) c_n = I[32:] cK_n = GetPubKey(public_key.pubkey, True) return cK_n, c_n
def _pubkey_point_to_bytes(public_key_point, compressed=True): """ Converts public key point to bytes (compressed format). :param public_key_point: :return: public key in compressed format """ arg_compr = 'compressed' if compressed else 'uncompressed' pki = VerifyingKey.from_public_point(public_key_point, curve=CURVE) pub_key = pki.to_string(encoding=arg_compr) return pub_key
def ecdsa_cose_to_key(encoded: bytes) -> VerifyingKey: decoded = loads(encoded) kty = decoded[CoseKey.KTY] curve = _ecdsa_curves[decoded[CoseKey.CRV]] x = int(decoded[CoseKey.X].hex(), 16) y = int(decoded[CoseKey.Y].hex(), 16) p = ellipticcurve.Point(curve.curve, x, y) key = VerifyingKey.from_public_point(p, curve) return key
def readkeys(self, path): """ read private keys from a directory, which must containser private.key, address and public.key """ self.address = open(path + "/address").read() self.private_key_js = open(path + "/private.key").read() self.public_key_js = open(path + "/public.key").read() sk_obj = json.loads(self.private_key_js) X = int(sk_obj['X']) Y = int(sk_obj['Y']) D = int(sk_obj['D']) self.public_key = VerifyingKey.from_public_point(ellipticcurve.Point(NIST256p.curve, X, Y), NIST256p, double_sha256) self.private_key = SigningKey.from_secret_exponent(D, NIST256p, double_sha256)
def verify_range_proofs(rg): HPow2 = hash_to_point(to_32_bytes_number(1)).pubkey.point H2 = [] for i in range(0, ATOMS): H2.append(VerifyingKey.from_public_point(HPow2, curve=crv).to_string()) HPow2 = HPow2 * 2 CiH = [] Ci = rg[0] [L1, s2, s] = rg[1] for i in range(0, ATOMS): negate_h2 = Point( crv.curve, VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.x(), (-VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.y()), crv.order, ) CiH.append( VerifyingKey.from_public_point( VerifyingKey.from_string(Ci[i], curve=crv).pubkey.point + negate_h2, curve=crv, ).to_string() ) verifiy_ASNL(Ci, CiH, L1, s2, s)
def mk_public_keyobj(self): if self.public_key is None: return if self.type == KeyType.ECDSA_SECP256k1_XY: self.key_len = int(len(self.public_key) / 2) x = self.to_bigint(self.public_key[0:self.key_len]) y = self.to_bigint(self.public_key[self.key_len:self.key_len * 2]) point = ecdsa.ellipticcurve.Point(ECDSA_CURVE.curve, x, y) if not ecdsa.ecdsa.point_is_valid(ECDSA_CURVE.generator, x, y): return self.public_key_object = VerifyingKey.from_public_point( point, curve=ECDSA_CURVE) elif self.type == KeyType.ECDSA_SECP256k1_X: self.key_len = len(self.public_key) x = self.to_bigint(self.public_key) # TODO: calc Y and make point object(X,Y) pass
def verify_message(address, signature, message): curve = curve_secp256k1 G = generator_secp256k1 order = G.order() # extract r,s from signature sig = base64.b64decode(signature) if len(sig) != 65: raise BaseException("Wrong encoding") r, s = util.sigdecode_string(sig[1:], order) nV = ord(sig[0]) if nV < 27 or nV >= 35: return False if nV >= 31: compressed = True nV -= 4 else: compressed = False recid = nV - 27 # 1.1 x = r + (recid / 2) * order # 1.3 alpha = (x * x * x + curve.a() * x + curve.b()) % curve.p() beta = modular_sqrt(alpha, curve.p()) y = beta if (beta - recid) % 2 == 0 else curve.p() - beta # 1.4 the constructor checks that nR is at infinity R = Point(curve, x, y, order) # 1.5 compute e from message: h = double_sha256(message) e = int(h.encode('hex'), 16) minus_e = -e % order # 1.6 compute Q = r^-1 (sR - eG) inv_r = numbertheory.inverse_mod(r, order) Q = inv_r * (s * R + minus_e * G) public_key = VerifyingKey.from_public_point(Q, curve=secp256k1) # check that Q is the public key public_key.verify_digest(sig[1:], h, sigdecode=util.sigdecode_string) # check that we get the original signing address addr = public_key_to_bc_address(encode_point(public_key, compressed)) if address == addr: return True else: # print addr return False
def validate_keys(sk: int, vk: Point) -> bool: std_sk = SigningKey.from_secret_exponent(sk, SECP256k1, sha256) std_vk = std_sk.get_verifying_key() std_point = ellipticcurve.Point(SECP256k1.curve, vk[0].value, vk[1].value) std_vk_from_point = VerifyingKey.from_public_point(std_point, SECP256k1, sha256) public_keys_match = std_vk_from_point.to_string() == std_vk.to_string() print( f"Your private key is {sk} and the respective public key is {represent_point(vk)}." ) if public_keys_match: print( f"This private key generates the same public key using py-ecdsa.") else: print( f"The public key generated using py-ecdsa is {str(std_vk.pubkey.point)}" ) return public_keys_match
def ecdh_decode(mask, amount, sender_public_key, receiver_secret_key): """ Function doing the decoding of ecdhEncode. Take the mask, the masked amount and appropriate public keys and return the decoded amount. :param mask: the hidden mask (32 bytes number) :param amount: the hidden amount (32 bytes number) :param sender_public_key: the public key generated by the sender to encode this amount (sec format) :param receiver_secret_key: the receiver sk (32 bytes number) :return: tuple consisting of new_mask: unhidden mask (32 bytes number) new_amount: unhidden amount (32 bytes number) """ send_public_key = VerifyingKey.from_string(sender_public_key, curve=crv) to_hash = VerifyingKey.from_public_point( send_public_key.pubkey.point * to_int_from_bytes(receiver_secret_key), curve=crv ).to_string() shared_secret_int = to_int_from_bytes(hashlib.sha256(to_hash).digest()) new_mask = (to_int_from_bytes(mask) - shared_secret_int) % crv.order new_amount = (to_int_from_bytes(amount) - shared_secret_int) % crv.order return to_32_bytes_number(new_mask), to_32_bytes_number(new_amount)
def from_sec(string, curve=curves.SECP256k1, hashfunc=sha1, validate_point=True): """Convert a public key in SEC binary format to a verifying key.""" # based on code from https://github.com/richardkiss/pycoin if string.startswith(b("\x04")): # uncompressed return VerifyingKey.from_string(string[1:], curve, hashfunc, validate_point) elif string.startswith(b("\x02")) or string.startswith(b("\x03")): # compressed is_even = string.startswith(b("\x02")) x = string_to_number(string[1:]) order = curve.order p = curve.curve.p() alpha = (pow(x, 3, p) + (curve.curve.a() * x) + curve.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if validate_point: assert ecdsa.point_is_valid(curve.generator, x, y) point = ellipticcurve.Point(curve.curve, x, y, order) return VerifyingKey.from_public_point(point, curve, hashfunc)
def get_ecdsa_verifying_key(pub): #some shenanigans required to validate a transaction sig; see #python.ecdsa PR #54. This will be a lot simpler when that's merged. #https://github.com/warner/python-ecdsa/pull/54/files if not pub[0] in ["\x02", "\x03"]: log.debug("Invalid pubkey") return None is_even = pub.startswith('\x02') x = string_to_number(pub[1:]) order = SECP256k1.order p = SECP256k1.curve.p() alpha = (pow(x, 3, p) + (SECP256k1.curve.a() * x) + SECP256k1.curve.b()) % p beta = square_root_mod_prime(alpha, p) if is_even == bool(beta & 1): y = p - beta else: y = beta if not point_is_valid(SECP256k1.generator, x, y): return None point = Point(SECP256k1.curve, x, y, order) return VerifyingKey.from_public_point(point, SECP256k1, hashfunc=hashlib.sha256)
def ecdsa_pub(x, y): """Create a public key from a public point""" point = ellipticcurve.Point(SECP256k1, x, y) return VerifyingKey.from_public_point(point, curve=SECP256k1)
def create_transaction( message, in_public_key, in_secret_key, in_amounts, destinations, out_amounts, mixin ): """ :param message: :param in_public_key: vector of public keys corresponding to the owner inputs(sec format) :param in_secret_key: vector of private keys corresponding to the public keys (format 32bytes number) :param in_amounts: vector of number corresponding to the amount coming from corresponding public key :param destinations: vector of public keys (sec format) :param out_amounts: vector of the different amounts going to the respective destinations public keys (int) :param mixin: the number of pk to get involved in the rings (int) :return: a list composed of destinations: a vector of destinations public keys as received (sec format) destinations_commitment: a vector of commitment assigned to each destinations public keys (32 bytes numbers) I: part of MLSAG, a vector of pk in sec format corresponding the the sha256 hash of the sender public key c_0: part of MLSAG, first sha3_256 (keccack) of the consecutive series of the MLSAG ss: part of MLSAG, a matrix of "random" 32 bytes number info: an array of ecdhEncode result containing the amount paid to the corresponding output pk range_signatures: vector of range_signatures (format TODO) """ print("------ Let's create a the transaction ------") assert 0 < mixin < MAX_MIXIN, ( "The number of ring participant should be between 0 and " + str(MAX_MIXIN) + "\n Aborting..." ) assert len(in_secret_key) == len(in_public_key) and len(in_amounts) == len( in_public_key ), "The number of private key doesn't match the number of public key or the number of input amounts.\nAborting..." assert len(destinations) == len( out_amounts ), "The number of outputs addresses should match the number of outputs amounts.\nAborting..." m = len(in_secret_key) for i in range(0, m): assert 0 < in_amounts[i] < MAX_AMOUNT, ( "The ingoing amount #" + str(i) + " should be between 0 and " + str(MAX_AMOUNT) + "\nAborting..." ) out_num = len(destinations) for i in range(0, out_num): assert 0 < out_amounts[i] < MAX_AMOUNT, ( "The outgoing amount #" + str(i) + " should be between 0 and " + str(MAX_AMOUNT) + "\nAborting..." ) for i in range(0, m): assert ( g.from_string(in_secret_key[i], curve=crv).verifying_key.to_string() == in_public_key[i] ), "One secret key doesn't match the corresponding public key.\nAborting..." print("------ All arguments are good, next ! ------") in_sk_masks = [] in_pk_masks = [] for i in range(0, m): sk_mask = to_32_bytes_number(random.randrange(crv.order)) in_sk_masks.append(sk_mask) pk_mask = g.from_string(sk_mask, curve=crv).verifying_key a_h = hash_to_point(to_32_bytes_number(1)).pubkey.point * in_amounts[i] pk_mask_point = pk_mask.pubkey.point + a_h in_pk_masks.append( VerifyingKey.from_public_point(pk_mask_point, curve=crv).to_string() ) destinations_commitment = [] info = [] range_signatures = [] out_sk_masks = [] for i in range(0, out_num): print("------ Creating rangeproof for amount#" + str(i + 1) + " ------") out_commit, out_sk_mask, rg = prove_range_signatures(out_amounts[i]) destinations_commitment.append(out_commit) out_sk_masks.append(out_sk_mask) range_signatures.append(rg) hidden_mask, hidden_amount, sender_pk = ecdh_encode( out_sk_mask, to_32_bytes_number(out_amounts[i]), destinations[i] ) info.append([hidden_mask, hidden_amount, sender_pk]) print("------ Rangeproofs are valid. Next ------") pk_matrix, pk_masks_matrix, index = populate_from_blockchain( in_public_key, in_pk_masks, mixin ) print("------ Matrix populated, going further! ------") if debug: (newMatrix, (I, c_0, ss)) = prepareMG( message, pk_matrix, pk_masks_matrix, in_secret_key, in_sk_masks, destinations_commitment, out_sk_masks, index, ) print("------ Transaction created with succes! ------") return ( newMatrix, destinations, destinations_commitment, I, c_0, ss, info, range_signatures, ) else: (newMatrix, (I, c_0, ss)) = prepareMG( message, pk_matrix, pk_masks_matrix, in_secret_key, in_sk_masks, destinations_commitment, out_sk_masks, index, ) print("------ Transaction created with succes! ------") return ( newMatrix, destinations, destinations_commitment, I, c_0, ss, info, range_signatures, )
def from_pair(cls, pair): x, y = pair point = Point(curve=SECP256k1.curve, x=x, y=y, order=SECP256k1.order) key = VerifyingKey.from_public_point(point, curve=SECP256k1) return cls(key)
def verify_message(self, address, signature, message): """Creates a public key from a message signature and verifies message Bitcoin uses a compact format for message signatures (for tx sigs it uses normal DER format). The format has the normal r and s parameters that ECDSA signatures have but also includes a prefix which encodes extra information. Using the prefix the public key can be reconstructed from the signature. | Prefix values: | 27 - 0x1B = first key with even y | 28 - 0x1C = first key with odd y | 29 - 0x1D = second key with even y | 30 - 0x1E = second key with odd y If key is compressed add 4 (31 - 0x1F, 32 - 0x20, 33 - 0x21, 34 - 0x22 respectively) Raises ------ ValueError If signature is invalid """ sig = b64decode(signature.encode('utf-8')) if len(sig) != 65: raise ValueError('Invalid signature size') # get signature prefix, compressed and recid (which key is odd/even) prefix = sig[0] if prefix < 27 or prefix > 35: return False if prefix >= 31: compressed = True recid = prefix - 31 else: compressed = False recid = prefix - 27 # create message digest -- note double hashing message_magic = add_magic_prefix(message) message_digest = hashlib.sha256( hashlib.sha256(message_magic).digest()).digest() # # use recid, r and s to get the point in the curve # # get signature's r and s r, s = sigdecode_string(sig[1:], _order) # ger R's x coordinate x = r + (recid // 2) * _order # get R's y coordinate (y**2 = x**3 + 7) y_values = sqrt_mod((x**3 + 7) % _p, _p, True) if (y_values[0] - recid) % 2 == 0: y = y_values[0] else: y = y_values[1] # get R (recovered ephemeral key) from x,y R = ellipticcurve.Point(_curve, x, y, _order) # get e (hash of message encoded as big integer) e = int(hexlify(message_digest), 16) # compute public key Q = r^-1 (sR - eG) # because Point substraction is not defined we will instead use: # Q = r^-1 (sR + (-eG) ) minus_e = -e % _order inv_r = numbertheory.inverse_mod(r, _order) Q = inv_r * (s * R + minus_e * _G) # instantiate the public key and verify message public_key = VerifyingKey.from_public_point(Q, curve=SECP256k1) key_hex = hexlify(public_key.to_string()).decode('utf-8') pubkey = PublicKey.from_hex('04' + key_hex) if not pubkey.verify(signature, message): return False # confirm that the address provided corresponds to that public key if pubkey.get_address(compressed=compressed).to_string() != address: return False return True
def from_pair(cls, pair): x, y = pair point = Point(curve=SECP256k1.curve, x=x, y=y, order=SECP256k1.order) key = VerifyingKey.from_public_point(point, curve=SECP256k1) return cls(key)
def prepareMG( message, public_keys, public_key_commitments, in_sk, in_sk_mask, out_commitment, out_sk_masks, index, ): """ :param message: :param public_keys: matrix of public key (size: qxm, sec format) :param public_key_commitments: matrix of commitment for pk (size: qxm, 32bytes) :param in_sk: vector of private key (size: m, bytes32 format) :param in_sk_mask: vector of mask for the corresponding sk (size: m, 32bytes) :param out_commitment: vector of commitment for pk (hidden amount) (size: outPKsize, 32bytes) :param out_sk_masks: vector mask for out public keys (bytes32) :param index: index of where in the public_keys matrix our pks are located :return: same as gen_MG """ print("------ Preparing the matrix for the MG ------") rows_q = len(public_keys) if debug: assert ( len(public_keys) == len(public_key_commitments) and len(public_keys) > 0 ), "\ Mismatch in the number of public commitment and keys.\nAborting..." cols_m = len(public_keys[0]) if debug: assert ( len(in_sk) == len(in_sk_mask) and len(in_sk) == cols_m ), "Mismatch in the number of private keys or private key masks.\nAborting..." for i in range(0, rows_q): assert ( len(public_keys[i]) == len(public_key_commitments[i]) and len(public_keys[i]) == cols_m ), "Mismatch in the number of public commitment and keys.\nAborting..." assert 0 <= index < rows_q, ( "index: " + str(index) + " should be between 0 and " + str(rows_q) + " (the number of public key).\nAborting..." ) assert ( len(out_commitment) == len(out_sk_masks) and len(out_commitment) > 0 ), "Mismatch in the number of private commitment and keys.\nAborting..." matrix = [[None] * (cols_m + 1) for y in range(rows_q)] sk = [None] * (cols_m + 1) for i in range(cols_m): sk[i] = in_sk[i] if i == 0: sk[cols_m] = in_sk_mask[i] else: sk[cols_m] = add_2_32b(sk[cols_m], in_sk_mask[i]) for j in range(rows_q): matrix[j][i] = public_keys[j][i] if i == 0: matrix[j][cols_m] = VerifyingKey.from_string( public_key_commitments[j][i], curve=crv ).pubkey.point else: matrix[j][cols_m] = ( matrix[j][cols_m] + VerifyingKey.from_string( public_key_commitments[j][i], curve=crv ).pubkey.point ) for i in range(len(out_commitment)): sk[cols_m] = sub_2_32b(sk[cols_m], out_sk_masks[i]) for i in range(rows_q): for j in range(len(out_commitment)): point = VerifyingKey.from_string(out_commitment[j], curve=crv).pubkey.point matrix[i][cols_m] = ( matrix[i][cols_m] + VerifyingKey.from_public_point( Point( crv.curve, point.x(), (-point.y()) % crv.curve.p(), crv.order ), curve=crv, ).pubkey.point ) for j in range(rows_q): matrix[j][cols_m] = VerifyingKey.from_public_point( matrix[j][cols_m], curve=crv ).to_string() print("------ Done with the matrix for the MG ------") # TODO message return matrix, genMG(message, matrix, sk, index)
def genMG(message, matrix, sk, index): n = len(matrix) if debug: assert n > 0, "No public key received.\nAborting..." m = len(matrix[0]) if debug: assert m == len( sk ), "The number of secret key doesn't match the number of public key.\nAborting..." for i in range(0, n): assert ( len(matrix[i]) == m ), "Public key array is not rectangular.\nAborting..." assert m > 0, "No public key in the array.\nAborting..." assert 0 <= index < m, "Not a valid index.\nAborting..." for i in range(0, m): assert ( g.from_string(sk[i], curve=crv).verifying_key.to_string() == matrix[index][i] ), ( "One secret key doesn't match the public key. Index: " + str(i) + "\n\ Aborting..." ) message_bytes = bytes(message, "UTF-8") alpha = [None] * m I = [None] * m ss = [[None] * m] * n L = [[[None, None]] * m] * n R = [[[None, None]] * m] * n for j in range(0, m): sk_j_hash_pub_point = hash_to_point( matrix[index][j] ).pubkey.point * to_int_from_bytes(sk[j]) I[j] = VerifyingKey.from_public_point( sk_j_hash_pub_point, curve=crv ).to_string() alpha[j] = to_32_bytes_number(random.randrange(crv.order)) LPoint = g.from_string(alpha[j], curve=crv).verifying_key.pubkey.point L[index][j] = [LPoint.x(), LPoint.y()] alpha_hash_pub_point = hash_to_point_special( matrix[index][j] ).pubkey.point * to_int_from_bytes(alpha[j]) R[index][j] = [alpha_hash_pub_point.x(), alpha_hash_pub_point.y()] c_idx_1 = sha3.keccak_256( message_bytes + list_to_bytes(L[index]) + list_to_bytes(R[index]) ).digest() c = c_idx_1 c_0 = None for i in range(1, n): idx = (index + i) % n for j in range(0, m): # assert ss[idx][j] == None, "Hmm sounds bad" ss[idx][j] = to_32_bytes_number(random.randrange(crv.order)) c_PubK = VerifyingKey.from_string( matrix[idx][j], curve=crv ).pubkey.point * to_int_from_bytes(c) sj_G = g.from_string(ss[idx][j], curve=crv) L_point = c_PubK + sj_G.verifying_key.pubkey.point L[idx][j] = [L_point.x(), L_point.y()] c_I = VerifyingKey.from_string( I[j], curve=crv ).pubkey.point * to_int_from_bytes(c) R_point = ( hash_to_point_special(matrix[idx][j]).pubkey.point * to_int_from_bytes(ss[idx][j]) + c_I ) R[idx][j] = [R_point.x(), R_point.y()] c = sha3.keccak_256( message_bytes + list_to_bytes(L[idx]) + list_to_bytes(R[idx]) ).digest() if idx == n - 1: c_0 = c print("------ Done with generating the MLSAG ------") if debug: # sanity check: L_tmp = [[None, None]] * m R_tmp = [[None, None]] * m for j in range(0, m): ss[index][j] = to_32_bytes_number( ( to_int_from_bytes(alpha[j]) - to_int_from_bytes(c) * to_int_from_bytes(sk[j]) ) % crv.order ) c_PubK = VerifyingKey.from_string( matrix[index][j], curve=crv ).pubkey.point * to_int_from_bytes(c) sj_G = g.from_string(ss[index][j], curve=crv) L_point = c_PubK + sj_G.verifying_key.pubkey.point L_tmp[j] = [L_point.x(), L_point.y()] c_I = VerifyingKey.from_string( I[j], curve=crv ).pubkey.point * to_int_from_bytes(c) R_point = ( hash_to_point_special(matrix[index][j]).pubkey.point * to_int_from_bytes(ss[index][j]) + c_I ) R_tmp[j] = [R_point.x(), R_point.y()] c_tmp = sha3.keccak_256( message_bytes + list_to_bytes(L_tmp) + list_to_bytes(R_tmp) ).digest() assert ( L_tmp == L[index] and R_tmp == R[index] ), "Sanity check for computing ss[index] failed.\nAborting..." if debug: assert verifyMG( message, matrix, I, c_0, ss ), "Ring verification failed.\nAborting..." print("------ Done with verifying the MLSAG ------") return I, c_0, ss else: return I, c_0, ss
def __init__(self, pub_point: ecdsa.ellipticcurve.Point): self.verifying_key = VerifyingKey.from_public_point( pub_point, ecdsa.SECP256k1)
def generate_schnorr_non_linkable(x, P1, P2, index): """ :param x: 32 bytes number :param P1: public key (format string of bytes32 representation) :param P2: public key (format string of bytes32 representation) :param index: random value :return: """ # x: bytes32 number # P1: pubkey in to string format bytes32 # P2: pubkey in to string format bytes32 if not index: a = to_32_bytes_number(random.randrange(crv.order)) L1Point = g.from_string(a, curve=crv).verifying_key.pubkey.point s2 = to_32_bytes_number(random.randrange(crv.order)) c2 = hashlib.sha256( to_32_bytes_number(L1Point.x()) + to_32_bytes_number(L1Point.y()) ).digest() L2Point = g.from_string(s2, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P2, curve=crv).pubkey.point * to_int_from_bytes(c2) ) c1 = hashlib.sha256( to_32_bytes_number(L2Point.x()) + to_32_bytes_number(L2Point.y()) ).digest() s1 = to_32_bytes_number( (to_int_from_bytes(a) - to_int_from_bytes(x) * to_int_from_bytes(c1)) % crv.order ) # sanity check if debug: L1p = g.from_string(s1, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P1, curve=crv).pubkey.point * to_int_from_bytes(c1) ) assert ( VerifyingKey.from_public_point(L1p, curve=crv).to_string() == VerifyingKey.from_public_point(L1Point, curve=crv).to_string() ), "Sanity check failed in GenSchnorr 1\nAborting..." if index: a = to_32_bytes_number(random.randrange(crv.order)) L2Point = g.from_string(a, curve=crv).verifying_key.pubkey.point s1 = to_32_bytes_number(random.randrange(crv.order)) c1 = hashlib.sha256( to_32_bytes_number(L2Point.x()) + to_32_bytes_number(L2Point.y()) ).digest() L1Point = g.from_string(s1, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P1, curve=crv).pubkey.point * to_int_from_bytes(c1) ) c2 = hashlib.sha256( to_32_bytes_number(L1Point.x()) + to_32_bytes_number(L1Point.y()) ).digest() s2 = to_32_bytes_number( (to_int_from_bytes(a) - (to_int_from_bytes(x) * to_int_from_bytes(c2))) % crv.order ) # sanity check if debug: L2p = g.from_string(s2, curve=crv).verifying_key.pubkey.point + ( VerifyingKey.from_string(P2, curve=crv).pubkey.point * to_int_from_bytes(c2) ) assert ( VerifyingKey.from_public_point(L2p, curve=crv).to_string() == VerifyingKey.from_public_point(L2Point, curve=crv).to_string() ), "Sanity check failed in GenSchnorr 2\nAborting..." L1 = VerifyingKey.from_public_point(L1Point, curve=crv).to_string() return L1, s1, s2
def prove_range_signatures(amount): """ :param amount: the amount that should be proved (int) :return: a list made of C_pk: output commitment serving as a public key (to_string 32bytes format) mask: part of the private key for C_pk. mask * G + amount * H == C_pk, 32 bytes number format rg: vector of range proofs, each entry contain a vector of public key Ci and a aggregate signature. The aggregate signature itself contains L1: vector of public key (to_string format, 32bytes) s2: vector of 32 bytes number s: 32 bytes number, aggregate of s1 For more info on asig, see generate_ASNL(...) """ HPow2 = hash_to_point(to_32_bytes_number(1)).pubkey.point H2 = [] for i in range(0, ATOMS): H2.append(VerifyingKey.from_public_point(HPow2, curve=crv).to_string()) HPow2 = HPow2 * 2 def d2b(n, digits): b = [0] * digits i = 0 while n: b[i] = n & 1 i = i + 1 n >>= 1 return b bb = d2b(amount, ATOMS) # gives binary form of bb in "digits" binary digits mask = to_32_bytes_number(0) ai = [] Ci = [] CiH = [] print("------ Preparing different elements ------") for i in range(0, ATOMS): ai.append(to_32_bytes_number(random.randrange(crv.order))) mask = add_2_32b( mask, ai[i] ) # creating the total mask since you have to pass this to receiver... if bb[i] == 0: Ci.append(g.from_string(ai[i], curve=crv).verifying_key.to_string()) if bb[i] == 1: Ci.append( VerifyingKey.from_public_point( g.from_string(ai[i], curve=crv).verifying_key.pubkey.point + VerifyingKey.from_string(H2[i], curve=crv).pubkey.point, curve=crv, ).to_string() ) negateH2 = Point( crv.curve, VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.x(), (-VerifyingKey.from_string(H2[i], curve=crv).pubkey.point.y()), crv.order, ) CiH.append( VerifyingKey.from_public_point( VerifyingKey.from_string(Ci[i], curve=crv).pubkey.point + negateH2, curve=crv, ).to_string() ) if debug and bb[i] == 1: # Sanity check A + h2 - h2 == A assert ( g.from_string(ai[i], curve=crv).verifying_key.to_string() == CiH[i] ), ( "Sanity check failed in prove_range_signatures !" + bytes.hex(g.from_string(ai[i], curve=crv).verifying_key.to_string()) + " ---- " + bytes.hex(CiH[i]) ) if rang_sig_bool: L1, s2, s = generate_ASNL(ai, Ci, CiH, bb) if debug: verifiy_ASNL(Ci, CiH, L1, s2, s) asig = [L1, s2, s] rg = [Ci, asig] else: rg = 1 C_point = VerifyingKey.from_string(Ci[0], curve=crv).pubkey.point for i in range(1, len(Ci)): C_point = C_point + VerifyingKey.from_string(Ci[i], curve=crv).pubkey.point C = to_32_bytes_number(0) for i in range(0, len(Ci)): C = add_2_32b(C, Ci[i]) C_pk = VerifyingKey.from_public_point(C_point, curve=crv) if debug: x = ( hash_to_point(to_32_bytes_number(1)).pubkey.point * amount + g.from_string(mask, curve=crv).verifying_key.pubkey.point ) assert ( C_pk.to_string() == VerifyingKey.from_public_point(x, curve=crv).to_string() ), ( "Something went wrong in the genreation of the commitment! " + bytes.hex(C_pk.to_string()) + " should equal " + bytes.hex(VerifyingKey.from_public_point(x, curve=crv).to_string()) ) return C_pk.to_string(), mask, rg