def get_private_key(curve, msg_1, sign_1, msg_2, sign_2, hash_algo): """ Wrapper function to recover_private_key :param curve: Curve used in ECDSA key in Curve type :param msg_1: Cleartext message string :param sign_1: Base64 encoded signature of msg_1 :param msg_2: Cleartext message string :param sign_2: Base64 encoded signature of msg_2 :param hash_algo: hashlib type of used hashing algorithm :return: """ # Build Signature types from decoded DER signatures sig_1 = Signature(*rs_from_der(sign_1)) sig_2 = Signature(*rs_from_der(sign_2)) # Get hashes from messages and convert them to integer # Gmsg_1_int_hash = long(binascii.hexlify(digest(hash_algo, msg_1)), 16) # Gmsg_2_int_hash = long(binascii.hexlify(digest(hash_algo, msg_2)), 16) msg_1_int_hash = int(binascii.hexlify(digest(hash_algo, msg_1)), 16) msg_2_int_hash = int(binascii.hexlify(digest(hash_algo, msg_2)), 16) if verbosity >= 2: print("Message : '{}'\n\thashed to : '{}'".format( msg_1, msg_1_int_hash)) print("Message : '{}'\n\thashed to : '{}'".format( msg_2, msg_2_int_hash)) return recover_signing_key(curve, msg_1_int_hash, sig_1, msg_2_int_hash, sig_2, hash_algo)
async def u2f_decrypt(self, key, value, salt, iterations): value_encrypted, key_handle, public_key_hash = itemgetter( 'value_encrypted', 'key_handle', 'public_key_hash')(value) challenge = secrets.token_hex(32) u2f_response = await self.u2f_authenticate(challenge, key_handle, control=U2F_AuthControl.DONT_ENFORCE_USER_PRESENCE_AND_SIGN) # with the signature and the message for which the signature was generated # two publik key candidates can be calculated r,s = u2f_parse_signature(u2f_response.signature) signature = Signature(r,s) message = u2f_response.message(challenge, self.application) message_hash = sha256(message).digest() message_int = int.from_bytes(message_hash, byteorder='big') public_keys = signature.recover_public_keys(message_int, NIST256p.generator) # compare the public key candidates against the stored hash of the public # key from the registration for public_key in public_keys: public_key_bytes = bytes([4]) + \ public_key.point.x().to_bytes(32, byteorder='big') + \ public_key.point.y().to_bytes(32, byteorder='big') if sha256(public_key_bytes).digest() == public_key_hash: break else: raise Exception('no public key found') secret = pbkdf2_hmac('sha256', public_key_bytes + key.encode('utf-8'), salt, iterations) fernet = Fernet(base64.urlsafe_b64encode(secret)) value_decrypted = fernet.decrypt(value_encrypted).decode('utf-8') return value_decrypted
def verify_vin_old(txid, index): # get raw transaction (txid) <-- vin[0]: scriptSig rpc = BtcRpc("http://*****:*****@127.0.0.1:8332") rawtx = rpc.rpc.getrawtransaction(txid) jsontxverbose = rpc.rpc.getrawtransaction(txid, 1) #pprint.pprint(jsontxverbose) jsontx = pybitcointools.deserialize(rawtx) pprint.pprint(jsontx) scriptSigasm = jsontxverbose['vin'][index]['scriptSig']['asm'] logger.debug(scriptSigasm) scriptSig = jsontx['ins'][index]['script'] sigpubdecoded = asn1der.decode( scriptSig.decode("hex")[1:]) # skip first push sig = long(sigpubdecoded[0][0]), long(sigpubdecoded[0][1]) pubkey = sigpubdecoded[1] sighash_type = pubkey[0] logger.debug("sighash type: %r" % sighash_type) push = pubkey[1] btc_pubkey_type = pubkey[2] pubkey = pubkey[3:] logger.debug("r %s s %s" % (hex(sig[0]), hex(sig[1]))) logger.debug(pubkey.encode("hex")) # generate signdata # replace input script with funding script of 17SkEw2md5avVNyYgj6RiXuQKNwkXaxFyQ for txin in jsontx['ins']: txin['script'] = '' funding_txid = jsontxverbose['vin'][index]['txid'] funding_tx = rpc.rpc.getrawtransaction(funding_txid, 1) #pprint.pprint(funding_tx) funding_script = funding_tx['vout'][0]['scriptPubKey']['hex'] jsontx['ins'][index]['script'] = funding_script signdata = pybitcointools.serialize(jsontx) + "01000000" #SIGHASH ALL import hashlib digest = hashlib.sha256(hashlib.sha256( signdata.decode("hex")).digest()).digest() logger.debug(digest[::-1].encode("hex")) vk = VerifyingKey.from_string(pubkey, curve=curve) logger.debug("verify --> %s " % (vk.pubkey.verifies( int(digest.encode("hex"), 16), Signature(sig[0], sig[1])))) #print vk.verify_digest(scriptSigasm.split("[ALL]",1)[0].decode("hex"), digest, sigdecode=ecdsa.util.sigdecode_der) return BTCSignature( sig=Signature(sig[0], sig[1]), h=int(digest.encode("hex"), 16), pubkey=pubkey, )
def selftest(): public_key_hex = 'a50eb66887d03fe186b608f477d99bc7631c56e64bb3af7dc97e71b917c5b364' + '7954da3444d33b8d1f90a0d7168b2f158a2c96db46733286619fccaafbaca6bc' msghash1 = '01b125d18422cdfa7b153f5bcf5b01927cf59791d1d9810009c70cd37b14f4e6' msghash2 = '339ff7b1ced3a45c988b3e4e239ea745db3b2b3fda6208134691bd2e4a37d6e1' sig1_hex = '304402200861cce1da15fc2dd79f1164c4f7b3e6c1526e7e8d85716578689ca9a5dc349d02206cf26e2776f7c94cafcee05cc810471ddca16fa864d13d57bee1c06ce39a3188' sig2_hex = '304402200861cce1da15fc2dd79f1164c4f7b3e6c1526e7e8d85716578689ca9a5dc349d02204ba75bdda43b3aab84b895cfd9ef13a477182657faaf286a7b0d25f0cb9a7de2' t = asn1der.decode(sig1_hex.decode("hex")) sig1 = Signature(long(t[0][0]), long(t[0][1])) t = asn1der.decode(sig2_hex.decode("hex")) sig2 = Signature(long(t[0][0]), long(t[0][1])) print sig1.r, sig1.s print sig2.r, sig2.s print msghash1 print msghash2 print public_key_hex sigx1 = BTCSignature(sig=sig1, h=long(msghash1, 16), pubkey=public_key_hex.decode("hex")) sigx2 = BTCSignature(sig=(sig2.r, sig2.s), h=long(msghash2, 16), pubkey=public_key_hex.decode("hex")) print "%r" % sigx1.recover_nonce_reuse(sigx2) print sigx1.signingkey print sigx1.to_btc_pubkey(), sigx1.to_btc_privkey() print sigx1.pubkey_to_address(), sigx1.privkey_to_wif() print sigx1.export_key() print "----sigx2---" sig1 = EcDsaSignature(sig=sig1, h=msghash1.decode("hex"), pubkey=public_key_hex.decode("hex")) sig2 = EcDsaSignature(sig=(sig2.r, sig2.s), h=msghash2.decode("hex"), pubkey=public_key_hex.decode("hex")) print sig1.recover_nonce_reuse(sig2) print sig1.export_key() raw_input("--End of Selftest -- press any key to continue--")
def sign_in_der(signing_key, message, hash_algo): """ Given a SigningKey and message, signs the latter and encodes signature into DER format Parts of code are taken from ecdsa library :param signing_key: :param message: :param hash_algo: :return: """ # Get hash from message and convert it to integer _hash = digest(hash_algo, message) h_int = int(binascii.hexlify(_hash), 16) r, s = signing_key.sign_number(h_int) d = der.encode_sequence(der.encode_integer(r), der.encode_integer(s)) der_signature = base64.b64encode(d) if verbosity >= 2: print("") print("[DBG] hash (hex) : " + str(binascii.hexlify(hash))) print("[DBG] r (" + str(len(str(hex(r)))) + ") : " + str(hex(r))) print("[DBG] s (" + str(len(str(hex(s)))) + ") : " + str(hex(s))) print("[DBG] hex : " + str(binascii.hexlify(d))) print("[DBG] der : " + str(der_signature)) sig = Signature(*rs_from_der(der_signature)) assert signing_key.get_verifying_key().pubkey.verifies( h_int, sig), "Message signed but verification failed !" print("Message successfully verified.") return der_signature
def recover_from_hash(curve, r, s1, h1, s2, h2, hashfunc): """ :param curve: :param r: :param s1: :param h1: :param s2: :param h2: :param hashfunc: :return: """ # Extract order from curve order = curve.order # Precomputed values for minor optimisation r_inv = inverse_mod(r, order) h = (h1 - h2) % order # # Signature is still valid whether s or -s mod curve_order (or n) # s*k-h # Try different possible values for "random" k until hit for k_try in (s1 - s2, s1 + s2, -s1 - s2, -s1 + s2): # Retrieving actual k k = (h * inverse_mod(k_try, order)) % order if verbosity >= 2: print("Trying nonce value : '{}'".format(k)) # Secret exponent secexp = (((((s1 * k) % order) - h1) % order) * r_inv) % order if verbosity >= 2: print("Secret exposant : '{}'".format(secexp)) # Building the secret key signing_key = SigningKey.from_secret_exponent(secexp, curve=curve, hashfunc=hashfunc) if verbosity >= 2: print("Trying signing key : '{}'".format(signing_key.to_pem())) # Verify if build key is appropriate if signing_key.get_verifying_key().pubkey.verifies( h1, Signature(r, s1)): if verbosity >= 1: print("Success !") return signing_key return None
def verify(self, pubkey_buffer, hash_buffer): """ Verify a digital signature. :param pubkey_buffer: Public key as bytes :param hash_buffer: hash of the message :return: True if this signature is valid """ assert isinstance(hash_buffer, bytes) assert isinstance(pubkey_buffer, bytes) hash_int = _hash_to_int(hash_buffer) point = _pubkey_point_from_bytes(pubkey_buffer) pk = Public_key(g, point) obj = Signature(self.r, self.s) return pk.verifies(hash_int, obj)
def sign(signing_key, message, hash_algo): """ :param signing_key: :param message: :param hash_algo: :return: """ # Get hash from message and convert it to integer _hash = digest(hash_algo, message) h_int = int(binascii.hexlify(_hash), 16) # Sign and get r and s r, s = signing_key.sign_number(h_int) # Build Signature return Signature(r, s)
def get_key_from_hash(): m_hash1 = '21298df8a3277357ee55b01df9530b535cf08ec1' sig1_hex = '13d8f71de2338048bcddd4846ea9762fa022172b6602f269c519892d8bf7e94f77608e0387a7ba5392bd1e2b4ded1048133fb584b7686233af00a6e7c5d427e7' m_hash2 = 'c692d6a10598e0a801576fdd4ecf3c37e45bfbc4' sig2_hex = '13d8f71de2338048bcddd4846ea9762fa022172b6602f269c519892d8bf7e94fdcb6d55b347bfbe8c6a37e2b7c6ca764d7bd07f52d56df2ff80df7a59cbe51ec' m_hash1 = int(m_hash1, 16) r = int(sig1_hex[:len(sig1_hex) // 2], 16) sig1 = int(sig1_hex[len(sig1_hex) // 2:], 16) m_hash2 = int(m_hash2, 16) sig2 = int(sig2_hex[len(sig2_hex) // 2:], 16) print("m_hash1 = " + hex(m_hash1)) print("sig1 = " + hex(sig1)) print("m_hash2 = " + hex(m_hash2)) print("sig2 = " + hex(sig2)) print("r = " + hex(r)) r_i = inverse_mod(r, curve.order) m_h_diff = (m_hash1 - m_hash2) % curve.order for k_try in (sig1 - sig2, sig1 + sig2, -sig1 - sig2, -sig1 + sig2): k = (m_h_diff * inverse_mod(k_try, curve.order)) % curve.order s_E = (((((sig1 * k) % curve.order) - m_hash1) % curve.order) * r_i) % curve.order key = SigningKey.from_secret_exponent(s_E, curve=curve, hashfunc=hash_algorithm) if key.get_verifying_key().pubkey.verifies(m_hash1, Signature(r, sig1)): print("ECDSA Private Key = " + "".join("{:02x}".format(c) for c in key.to_string()) ) # If we got here we found a solution return key
def verify_vin(txid, index): txdump = dump_tx_ecdsa(txid, index) #i, pub, txid, s, r, x, z # | | \--- hash # | \------ pub decoded? # \---------------------- pub orig? import pprint pprint.pprint(txdump) print txdump['z'].decode("hex") print int(txdump['z'],16) def fix_pubkey(p): if p.startswith("04"): return p[2:] return p txdump['pub'] = fix_pubkey(txdump['pub']) #vk = VerifyingKey.from_public_point(int(txdump['x'],16),curve=curve) #vk = VerifyingKey.from_string(txdump['pub'], curve=curve) #print vk #logger.debug("verify --> %s " % (vk.pubkey.verifies(int(digest.encode("hex"), 16), Signature(sig[0], sig[1])))) # get raw transaction (txid) <-- vin[0]: scriptSig rpc = BtcRpc("http://*****:*****@127.0.0.1:8332") rawtx = rpc.rpc.getrawtransaction(txid) jsontxverbose = rpc.rpc.getrawtransaction(txid,1) #pprint.pprint(jsontxverbose) jsontx = pybitcointools.deserialize(rawtx) pprint.pprint(jsontx) scriptSigasm = jsontxverbose['vin'][index]['scriptSig']['asm'] logger.debug(scriptSigasm) scriptSig = jsontx['ins'][index]['script'] sigpubdecoded = asn1der.decode(scriptSig.decode("hex")[1:]) # skip first push sig = long(sigpubdecoded[0][0]), long(sigpubdecoded[0][1]) pubkey = sigpubdecoded[1] sighash_type = pubkey[0] logger.debug("sighash type: %r" % sighash_type) push = pubkey[1] btc_pubkey_type = pubkey[2] pubkey = pubkey[3:] logger.debug("r %s s %s"%(hex(sig[0]),hex(sig[1]))) logger.debug("pubkey: %r"%pubkey.encode("hex")) logger.debug("txdump: %r"%txdump['pub']) ''' # generate signdata # replace input script with funding script of 17SkEw2md5avVNyYgj6RiXuQKNwkXaxFyQ for txin in jsontx['ins']: txin['script']='' funding_txid = jsontxverbose['vin'][index]['txid'] funding_tx = rpc.rpc.getrawtransaction(funding_txid,1) #pprint.pprint(funding_tx) funding_script = funding_tx['vout'][0]['scriptPubKey']['hex'] jsontx['ins'][index]['script']=funding_script signdata= pybitcointools.serialize(jsontx) + "01000000" #SIGHASH ALL import hashlib digest = hashlib.sha256(hashlib.sha256(signdata.decode("hex")).digest()).digest() logger.debug(digest[::-1].encode("hex")) pause("--->") ''' pause("create verifying key...") vk = VerifyingKey.from_string(txdump['pub'].decode("hex"), curve=curve) digest = txdump['z'] print repr(pubkey) print repr(txdump['pub']) z = int(digest.decode("hex"),16) verifies = vk.pubkey.verifies(z,Signature(sig[0],sig[1])) logger.debug("verify --> %s "%(verifies)) if not verifies: pause("--verify false!--",critical=True) #print vk.verify_digest(scriptSigasm.split("[ALL]",1)[0].decode("hex"), digest, sigdecode=ecdsa.util.sigdecode_der) return BTCSignature(sig=Signature(sig[0],sig[1]), h=z, pubkey=pubkey, )
def recover_Q(ra, sa, za): g = PointJacobi(CurveFp(mod, a, b), G[0], G[1], G[2], n, generator=True) Q = Signature(ra, sa).recover_public_keys(za, g)[0] return (Q.point.x(), Q.point.y(), 1)