def do_test(secret_exponent, val_list): public_point = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent) for v in val_list: signature = sign(generator_secp256k1, secret_exponent, v) r = verify(generator_secp256k1, public_point, v, signature) assert r == True signature = signature[0],signature[1]+1 r = verify(generator_secp256k1, public_point, v, signature) assert r == False
def do_test(secret_exponent, val_list): public_point = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent) for v in val_list: signature = sign(generator_secp256k1, secret_exponent, v) r = verify(generator_secp256k1, public_point, v, signature) # Check that the 's' value is 'low', to prevent possible transaction malleability as per # https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures assert signature[1] <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 assert r == True signature = signature[0],signature[1]+1 r = verify(generator_secp256k1, public_point, v, signature) assert r == False
def ITTV(): from pycoin import ecdsa as ecd key = sign.Key("62fbe2") obj, j = key.sign_transaction( **{ "recipient_address": "053b3ebd1e15f06dfc7e125eadbd31cfec220895", "value": 10000000, "fee": 100 }) tx1 = Transaction(json.dumps(obj)) tx2 = Transaction(tx1.jsontrans) obj['to'] = "1234567890" trans = Transaction(json.dumps(obj)) hashes = [ [trans.hash, "False"], # Modified Recipient Hash [trans._d['transactionDataHash'], "True"], # Valid Hash [ "cfd713049033cffda22f25c399b182691716c2b68346d419d5b1edf62fc63740", "False" ], [tx1.hash, "True"], [tx2.hash, "True"] ] for _hash, exp_res in hashes: printer.print("======Testing=======") printer.print(f"HASH: {_hash}") result = ecd.verify(ecd.generator_secp256k1, key.pubkey, int(_hash, base=16), trans.senderSignature) printer.print(f"VALID? {result}") printer.print(f"Expected result: {exp_res}")
def valid(self): if self.transactionDataHash != self.hash: return False # possible_keypairs = ecd.possible_public_pairs_for_signature( # ecd.generator_secp256k1, # int(self.hash, 16), # self.senderSignature) #for keypair in possible_keypairs: # print(keypair) # verified = ecd.verify( # ecd.generator_secp256k1, # keypair, # int(self.hash, base=16), # self.senderSignature) # if verified: # return True verified = ecd.verify( ecd.generator_secp256k1, self.senderPubKey, int(self.hash, base=16), self.senderSignature) return verified
def solve_finalize_commit(self, **kwargs): hash160_lookup = kwargs.get("hash160_lookup") sign_value = kwargs.get("sign_value") signature_type = kwargs.get("signature_type") existing_script = kwargs.get("existing_script") # FIXME validate on receiving the commit # validate payer sig opcode, data, pc = tools.get_opcode(existing_script, 0) # OP_0 opcode, payer_sig, pc = tools.get_opcode(existing_script, pc) sig_pair, actual_signature_type = parse_signature_blob(payer_sig) try: public_pair = encoding.sec_to_public_pair(self.payer_sec) sig_pair, signature_type = parse_signature_blob(payer_sig) valid = ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_pair) if not valid: raise Exception("Invalid payer public_pair!") except (encoding.EncodingError, UnexpectedDER): raise Exception("Invalid payer public_pair!") # sign private_key = hash160_lookup.get(encoding.hash160(self.payee_sec)) secret_exponent, public_pair, compressed = private_key payee_sig = self._create_script_signature( secret_exponent, sign_value, signature_type ) script_text = "OP_0 {payer_sig} {payee_sig} OP_1".format( payer_sig=b2h(payer_sig), payee_sig=b2h(payee_sig) ) return tools.compile(script_text)
def sign_and_verify_transaction(recipient_address: str, value: int, dateCreated: str, sender_priv_key_hex: str): print("Generate and sign a transaction") print("-------------------------------") sender_priv_key = int(sender_priv_key_hex, 16) print("sender private key:", sender_priv_key_hex) sender_pub_key = (generator_secp256k1 * sender_priv_key).pair() pub_key_compressed = hex(sender_pub_key[0])[2:] + str( sender_pub_key[1] % 2) print("sender public key:", pub_key_compressed) sender_address = ripemd160(pub_key_compressed) print("sender address:", sender_address) tran = { 'from': sender_address, 'to': recipient_address, 'value': value, 'dateCreated': dateCreated, 'senderPubKey': pub_key_compressed } json_encoder = json.JSONEncoder(separators=(',', ':')) tran_json = json_encoder.encode(tran) print("transaction (json):", tran_json) tran_hash = sha256(tran_json) print("transaction hash (sha256):", hex(tran_hash)[2:]) tran_signature = sign(generator_secp256k1, sender_priv_key, tran_hash) print("transaction signature:", tran_signature) tran['senderSignature'] = [ hex(tran_signature[0])[2:], hex(tran_signature[1])[2:] ] print("signed transaction:") print(json.JSONEncoder(indent=2).encode(tran)) valid = verify(generator_secp256k1, sender_pub_key, tran_hash, tran_signature) print("Signature valid? " + str(valid))
def verify_transaction(self): #if len(self.sender_signature)>0: pub_key = self.sender_public_key signature = self.sender_signature self.is_verified = verify(generator_secp256k1, pub_key, int(self.transaction_sha256hex, 16), signature)
def test_sign(self): for se in ["47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"] + [x * 64 for x in "123456789abcde"]: secret_exponent = int(se, 16) val = 28832970699858290 #int.from_bytes(b"foo bar", byteorder="big") sig = sign(generator_secp256k1, secret_exponent, val) public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent) v = verify(generator_secp256k1, public_pair, val, sig) self.assertTrue(v) sig1 = (sig[0] + 1, sig[1]) v = verify(generator_secp256k1, public_pair, val, sig1) self.assertFalse(v) public_pairs = possible_public_pairs_for_signature(generator_secp256k1, val, sig) self.assertIn(public_pair, public_pairs) print(se)
def test_sign(self): for se in ["47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012"] + [x * 64 for x in "123456789abcde"]: secret_exponent = int(se, 16) val = int.from_bytes(b"foo bar", byteorder="big") sig = sign(generator_secp256k1, secret_exponent, val) public_pair = public_pair_for_secret_exponent(generator_secp256k1, secret_exponent) v = verify(generator_secp256k1, public_pair, val, sig) self.assertTrue(v) sig1 = (sig[0] + 1, sig[1]) v = verify(generator_secp256k1, public_pair, val, sig1) self.assertFalse(v) public_pairs = possible_public_pairs_for_signature(generator_secp256k1, val, sig) self.assertIn(public_pair, public_pairs) print(se)
def verify_signature(self): is_odd = (int(self.sender_pub_key[-1:]) % 2 == 0) pub_pair = public_pair_for_x(generator_secp256k1, int(self.sender_pub_key[:-1], 16), is_odd) signature_pair = (int(self.sender_signature[0], 16), int(self.sender_signature[1], 16)) return verify(generator_secp256k1, pub_pair, self.transaction_data_hash, signature_pair)
def verify_transaction(public_key, hashed_data, signature): """ Verifies a transaction based ot its signature, data and owners public key :param public_key: <tuple<int,int>> see: generate_public_key :param hashed_data: <int> that represent the data in the transaction :param signature: <tuple<int,int>> :return: <bool> """ try: return verify(generator_secp256k1, public_key, hashed_data, signature) except: print("Provided data is invalid.") return False
def validate_transaction_data(transaction): # if transaction['from'] == 'coinbase': # return True, "201:TransactionIsCoinbase" # pubkey = transaction['senderPubKey'] # if not validate_sender_as_signer(transaction): # return False, "301:SenderSignerMismatch" # # hash_trans = get_transaction_hash(transaction) # sig_trans = transaction['senderSignature'] # result = ecd.verify( ecd.generator_secp256k1, # pubkey, # int(hash_trans, base=16), # sig_trans) # if result: # return True, "200:TransactionValid" # else: # return False, "300:TransactionInvalid" #
def solve_finalize_commit(self, **kwargs): hash160_lookup = kwargs.get("hash160_lookup") signature_type = kwargs.get("signature_type") existing_script = kwargs.get("existing_script") # validate existing script reference_script_hex = _compile_commit_scriptsig( "deadbeef", "deadbeef", b2h(self.script)) _validate(reference_script_hex, b2h(existing_script)) # check provided payer signature try: opcode, data, pc = tools.get_opcode(existing_script, 0) # OP_0 opcode, payer_sig, pc = tools.get_opcode(existing_script, pc) # verify signature type sig_r_s, actual_signature_type = parse_signature_blob(payer_sig) assert (signature_type == actual_signature_type) # verify payer signature public_pair = encoding.sec_to_public_pair(self.payer_sec) sign_value = kwargs.get("sign_value") public_pair = encoding.sec_to_public_pair(self.payer_sec) sign_value = kwargs["signature_for_hash_type_f"]( signature_type, kwargs["script_to_hash"]) if not ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_r_s): raise InvalidPayerSignature("invalid r s values") except UnexpectedDER: raise InvalidPayerSignature("not in DER format") # sign private_key = hash160_lookup.get(encoding.hash160(self.payee_sec)) secret_exponent, public_pair, compressed = private_key payee_sig = self._create_sig(secret_exponent, **kwargs) script_asm = COMMIT_SCRIPTSIG.format(payer_sig=b2h(payer_sig), payee_sig=b2h(payee_sig)) return tools.compile(script_asm)
def sign_and_verify_transactions(recipient_address: str, value: int, fee: int, date_created: str, sender_priv_key_hex: str): print("sender private key hex: ", sender_priv_key_hex) sender_priv_key = private_key_hex_to_int(sender_priv_key_hex) print("sender private key: ", sender_priv_key) pub_key_compressed, sender_address = extract_public_key_and_address( sender_priv_key) transaction = { 'from': sender_address, 'to': recipient_address, 'senderPubKey': pub_key_compressed, 'value': value, 'fee': fee, 'dataCreated': date_created, } json_encoder = json.JSONEncoder(separators=(',', ':')) tran_json = json_encoder.encode(transaction) print("transaction(json):", tran_json) tran_hash = sha256(tran_json) print("transaction hash (sha256): ", hex(tran_hash)[2:]) tran_signature = sign(generator_secp256k1, sender_priv_key, tran_hash) print("transaction signature: ", tran_signature) transaction['senderSignature'] = [ hex(tran_signature[0])[2:], hex(tran_signature[1])[2:] ] print("signed transaction: ") print(json.JSONEncoder(indent=2).encode(transaction)) pub_key = private_key_to_public_key(sender_priv_key) valid = verify(generator_secp256k1, pub_key, tran_hash, tran_signature) print("Is signature valid? " + str(valid)) return valid
def sign_transaction(self, **data): to_address = data.pop("recipient_address") value = data.pop("value") fee = data.pop("fee") transaction = { "from": self.address, "to": to_address, "senderPubKey": self.pubkey, "value": value, "fee": fee, "dateCreated": int(datetime.datetime.now().timestamp()) } json_trans = json.JSONEncoder(separators=(',', ':')).encode(transaction) hash_trans = ETH_misc.sha256(json_trans) sig_trans = ecd.sign(ecd.generator_secp256k1, self.int, int(hash_trans, base=16)) transaction['senderSignature'] = [hex(sig_trans[0])[2:], hex(sig_trans[1])[2:]] #print(f"=====Transaction JSON=====\n{json_trans}") #print(f"=====Transaction Hash=====\n{hash_trans}") #print(f"=====Transaction Sig=====\n{sig_trans}") #print(f"=====Signed Transaction=====\n{json.dumps(transaction, indent=2)}") verification = ecd.verify( ecd.generator_secp256k1, self.pubkey, int(hash_trans, base=16), sig_trans) #print(f"VALIDATION: {verification}") transaction['transactionDataHash'] = hash_trans transaction['senderSignature'] = sig_trans transaction['transferSuccessful'] = False transaction['minedInBlockIndex'] = None return transaction, json.dumps(transaction)
def verify(self, h, sig): """ Return whether a signature is valid for hash h using this key. """ val = intbytes.from_bytes(h) pubkey = self.public_pair() rs = sigdecode_der(sig) if self.public_pair() is None: # find the pubkey from the signature and see if it matches # our key possible_pubkeys = ecdsa.possible_public_pairs_for_signature( ecdsa.generator_secp256k1, val, rs) hash160 = self.hash160() for candidate in possible_pubkeys: if hash160 == public_pair_to_hash160_sec(candidate, True): pubkey = candidate break if hash160 == public_pair_to_hash160_sec(candidate, False): pubkey = candidate break else: # signature is using a pubkey that's not this key return False return ecdsa.verify(ecdsa.generator_secp256k1, pubkey, val, rs)
def verify(self, h, sig): """ Return whether a signature is valid for hash h using this key. """ val = from_bytes_32(h) pubkey = self.public_pair() rs = sigdecode_der(sig) if self.public_pair() is None: # find the pubkey from the signature and see if it matches # our key possible_pubkeys = ecdsa.possible_public_pairs_for_signature( ecdsa.generator_secp256k1, val, rs) hash160 = self.hash160() for candidate in possible_pubkeys: if hash160 == public_pair_to_hash160_sec(candidate, True): pubkey = candidate break if hash160 == public_pair_to_hash160_sec(candidate, False): pubkey = candidate break else: # signature is using a pubkey that's not this key return False return ecdsa.verify(ecdsa.generator_secp256k1, pubkey, val, rs)
def verify_transaction(pub_key,transaction_sha256hex,signature): #if len(self.sender_signature)>0: #pub_key = transaction.sender_public_key #signature = transaction.sender_signature return verify(generator_secp256k1, pub_key, int(transaction_sha256hex,16), signature)
def valid_secp256k1_signature(x, y, msg, r, s): return ecdsa.verify(ecdsa.generator_secp256k1, (x, y), global_hash(msg), (r, s))
def solve(self, **kwargs): """ The kwargs required depend upon the script type. hash160_lookup: dict-like structure that returns a secret exponent for a hash160 existing_script: existing solution to improve upon (optional) sign_value: the integer value to sign (derived from the transaction hash) signature_type: usually SIGHASH_ALL (1) """ # we need a hash160 => secret_exponent lookup db = kwargs.get("hash160_lookup") if db is None: raise SolvingError("missing hash160_lookup parameter") sign_value = kwargs.get("sign_value") signature_type = kwargs.get("signature_type") secs_solved = set() existing_signatures = [] existing_script = kwargs.get("existing_script") if existing_script: pc = 0 opcode, data, pc = tools.get_opcode(existing_script, pc) # ignore the first opcode while pc < len(existing_script): opcode, data, pc = tools.get_opcode(existing_script, pc) sig_pair, actual_signature_type = parse_signature_blob(data) for sec_key in self.sec_keys: try: public_pair = encoding.sec_to_public_pair(sec_key) sig_pair, signature_type = parse_signature_blob(data) v = ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_pair) if v: existing_signatures.append(data) secs_solved.add(sec_key) break except encoding.EncodingError: # if public_pair is invalid, we just ignore it pass for sec_key in self.sec_keys: if sec_key in secs_solved: continue if len(existing_signatures) >= self.n: break hash160 = encoding.hash160(sec_key) result = db.get(hash160) if result is None: continue secret_exponent, public_pair, compressed = result binary_signature = self._create_script_signature( secret_exponent, sign_value, signature_type) existing_signatures.append(b2h(binary_signature)) DUMMY_SIGNATURE = "OP_0" while len(existing_signatures) < self.n: existing_signatures.append(DUMMY_SIGNATURE) script = "OP_0 %s" % " ".join(s for s in existing_signatures) solution = tools.compile(script) return solution
from pycoin.ecdsa import generator_secp256k1, sign, verify import hashlib def keccak_hash(msg) : hash_bytes = hashlib.sha3_256(msg.encode("utf8")).digest() return int.from_bytes(hash_bytes, byteorder="big") msg = "some message" msg_hash = keccak_hash(msg) private_key = 9999999999999999999999999999999999999999999 signature = sign(generator_secp256k1, private_key, msg_hash) print("signature = " + str(signature)) public_key = (generator_secp256k1 * private_key).pair() print("public key: " + str(public_key)) valid = verify(generator_secp256k1, public_key, msg_hash, signature) print("Signature valid? " + str(valid)) tampered_msg_hash = keccak_hash("tampered msg") valid = verify(generator_secp256k1, public_key, tampered_msg_hash, signature) print("Signature (tampered msg) valid? " + str(valid))
def solve(self, **kwargs): """ The kwargs required depend upon the script type. hash160_lookup: dict-like structure that returns a secret exponent for a hash160 existing_script: existing solution to improve upon (optional) sign_value: the integer value to sign (derived from the transaction hash) signature_type: usually SIGHASH_ALL (1) """ # we need a hash160 => secret_exponent lookup db = kwargs.get("hash160_lookup") if db is None: raise SolvingError("missing hash160_lookup parameter") sign_value = kwargs.get("sign_value") signature_type = kwargs.get("signature_type") secs_solved = set() existing_signatures = [] existing_script = kwargs.get("existing_script") if existing_script: pc = 0 opcode, data, pc = tools.get_opcode(existing_script, pc) # ignore the first opcode while pc < len(existing_script): opcode, data, pc = tools.get_opcode(existing_script, pc) sig_pair, actual_signature_type = parse_signature_blob(data) for sec_key in self.sec_keys: try: public_pair = encoding.sec_to_public_pair(sec_key) sig_pair, signature_type = parse_signature_blob(data) v = ecdsa.verify(ecdsa.generator_secp256k1, public_pair, sign_value, sig_pair) if v: existing_signatures.append(data) secs_solved.add(sec_key) break except encoding.EncodingError: # if public_pair is invalid, we just ignore it pass for sec_key in self.sec_keys: if sec_key in secs_solved: continue if len(existing_signatures) >= self.n: break hash160 = encoding.hash160(sec_key) result = db.get(hash160) if result is None: continue secret_exponent, public_pair, compressed = result binary_signature = self._create_script_signature(secret_exponent, sign_value, signature_type) existing_signatures.append(b2h(binary_signature)) DUMMY_SIGNATURE = "OP_0" while len(existing_signatures) < self.n: existing_signatures.append(DUMMY_SIGNATURE) script = "OP_0 %s" % " ".join(s for s in existing_signatures) solution = tools.compile(script) return solution
def sendTransaction(): # try data = request.data parsed = json.loads(data.decode()) parsedBody = parsed['body'] parsedAddress = parsedBody['senderWalletAddress'] parsedSigningKey = parsedBody['senderPrivateKey'] parsedPublicKey = parsedBody['senderPublicKey'] parsedAmount = parsedBody['amount'] parsedData = parsedBody['data'] parsedRecipientAddress = parsedBody['recipientWalletAddress'] parsedBalance = parsedBody['balance'] # parsedBalance = 200 # parsedTotal = 120 # parsedAmount = 50 transactionFee = 0.3125 parsedTotal = float(transactionFee) + float(parsedAmount) sender_private_key = private_key_hex_to_int(parsedPublicKey) public_key_compressed, sender_address = extract_public_key_and_address( sender_private_key) transaction = { 'sender': parsedSigningKey, 'senderAddress': parsedAddress, 'to': parsedRecipientAddress, 'trueAmount': parsedAmount, 'amount': parsedTotal, 'dateCreated': getDateStamp(), 'hourCreated': getTimeStamp(), 'transactionFee': transactionFee, 'data': parsedData, 'balance': parsedBalance } validTransaction = Transaction() json_encoder = json.JSONEncoder(separators=(',', ':')) trans_json = json_encoder.encode(transaction) print("transaction (json):", trans_json) trans_hash = sha256(trans_json) print("transaction hash (sha256):", hex(trans_hash)[2:]) trans_signature = sign(generator_secp256k1, sender_private_key, trans_hash) print("transaction signature:", trans_signature) transaction['senderSignature'] = [ hex(trans_signature[0])[2:], hex(trans_signature[1]) ] print("sign transaction: ") print(json.JSONEncoder(indent=2).encode(transaction)) pub_key = private_key_to_public_key(sender_private_key) valid = verify(generator_secp256k1, pub_key, trans_hash, trans_signature) print("is signature valid? " + str(valid)) if valid == True: return validTransaction.addValidatedTransaction( trans_hash, parsedAddress, parsedRecipientAddress, parsedBalance, parsedTotal, parsedAmount) else: return jsonify({'status': False})
def verifyECDSAsecp256k1(msg, signature, pubKey): msgHash = sha3_256Hash(msg) valid = verify(generator_secp256k1, pubKey, msgHash, signature) return valid