def validate_signature_for_spend(txin, utxo: UnspentTxOut, txn):
pubkey_as_addr = pubkey_to_address(txin.unlock_pk)
verifying_key = ecdsa.VerifyingKey.from_string(
txin.unlock_pk, curve=ecdsa.SECP256k1)
if pubkey_as_addr != utxo.to_address:
raise TxUnlockError("Pubkey doesn't match")
try:
spend_msg = build_spend_message(
txin.to_spend, txin.unlock_pk, txin.sequence, txn.txouts)
verifying_key.verify(txin.unlock_sig, spend_msg)
except Exception:
logger.exception('Key verification failed')
raise TxUnlockError("Signature doesn't match")
return True
python类SECP256k1()的实例源码
def init_wallet(path=None):
path = path or WALLET_PATH
if os.path.exists(path):
with open(path, 'rb') as f:
signing_key = ecdsa.SigningKey.from_string(
f.read(), curve=ecdsa.SECP256k1)
else:
logger.info(f"generating new wallet: '{path}'")
signing_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
with open(path, 'wb') as f:
f.write(signing_key.to_string())
verifying_key = signing_key.get_verifying_key()
my_address = pubkey_to_address(verifying_key.to_string())
logger.info(f"your address is {my_address}")
return signing_key, verifying_key, my_address
# Misc. utilities
# ----------------------------------------------------------------------------
def btc( seed = None ):
'''Generate BTC address and key from seed'''
if not seed: return 32
private_key = b'\x80' + seed + b'\x01'
private_key += _sha256( _sha256( private_key ))[ :4 ]
public_key_uncomp = bytes( SigningKey. from_string( seed, curve = SECP256k1 ). get_verifying_key(). to_string() )
public_key = b'\x03' if public_key_uncomp[ -1 ] & 1 else b'\x02'
public_key += public_key_uncomp[ :32 ]
address = b'\x00' + _ripemd160( _sha256( public_key ))
address += _sha256( _sha256( address ))[ :4 ]
result = { 'key': _b58( private_key ), 'address': _b58( address )}
result[ None ] = result[ 'address' ]
return result
# xmr
def __init__(self, private_key=0):
if private_key == 0:
self.private_key = os.urandom(32)
self.printable_pk = str(binascii.hexlify(self.private_key), "ascii")
else:
self.printable_pk = private_key
self.private_key = binascii.unhexlify(private_key.encode('ascii'))
self.sk = ecdsa.SigningKey.from_string(self.private_key, curve = ecdsa.SECP256k1)
self.vk = self.sk.verifying_key
self.public_key = b"04" + binascii.hexlify(self.vk.to_string())
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(binascii.unhexlify(self.public_key)).digest())
self.hashed_public_key = b"00" + binascii.hexlify(ripemd160.digest())
self.checksum = binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify(self.hashed_public_key)).digest()).digest()[:4])
self.binary_addr = binascii.unhexlify(self.hashed_public_key + self.checksum)
self.addr = base58.b58encode(self.binary_addr)
def key_generate(self):
self.logger.info('key_generate()')
self.logger.debug('This will replace your public and private keys in 3 seconds...')
time.sleep(3)
self.private_key = SigningKey.generate(curve=SECP256k1, hashfunc=sha256)
self.public_key = self.private_key.get_verifying_key()
s = raw_input('Export keys to file for later use? [Y/N]')
if 'Y' in s.upper():
self.key_export()
self.key_register(self.public_key)
def _derive_y_from_x(self, x, is_even):
""" Derive y point from x point """
curve = ecdsa.SECP256k1.curve
# The curve equation over F_p is:
# y^2 = x^3 + ax + b
a, b, p = curve.a(), curve.b(), curve.p()
alpha = (pow(x, 3, p) + a * x + b) % p
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, p)
if (beta % 2) == is_even:
beta = p - beta
return beta
def compressed(self):
""" Derive compressed public key """
order = ecdsa.SECP256k1.generator.order()
p = ecdsa.VerifyingKey.from_string(bytes(self), curve=ecdsa.SECP256k1).pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
# y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
return (compressed)
def point(self):
""" Return the point for the public key """
string = unhexlify(self.unCompressed())
return ecdsa.VerifyingKey.from_string(string[1:], curve=ecdsa.SECP256k1).pubkey.point
def compressedpubkey(self):
""" Derive uncompressed public key """
secret = unhexlify(repr(self._wif))
order = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).curve.generator.order()
p = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
uncompressed = hexlify(bytes(chr(4), 'ascii') + x_str + y_str).decode('ascii')
return [compressed, uncompressed]
def recover_public_key(self, digest, signature, i):
""" Recover the public key from the the signature
"""
# See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily
curve = ecdsa.SECP256k1.curve
G = ecdsa.SECP256k1.generator
order = ecdsa.SECP256k1.order
yp = (i % 2)
r, s = ecdsa.util.sigdecode_string(signature, order)
# 1.1
x = r + (i // 2) * order
# 1.3. This actually calculates for either effectively 02||X or 03||X depending on 'k' instead of always for 02||X as specified.
# This substitutes for the lack of reversing R later on. -R actually is defined to be just flipping the y-coordinate in the elliptic curve.
alpha = ((x * x * x) + (curve.a() * x) + curve.b()) % curve.p()
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, curve.p())
y = beta if (beta - yp) % 2 == 0 else curve.p() - beta
# 1.4 Constructor of Point is supposed to check if nR is at infinity.
R = ecdsa.ellipticcurve.Point(curve, x, y, order)
# 1.5 Compute e
e = ecdsa.util.string_to_number(digest)
# 1.6 Compute Q = r^-1(sR - eG)
Q = ecdsa.numbertheory.inverse_mod(r, order) * (s * R + (-e % order) * G)
# Not strictly necessary, but let's verify the message for paranoia's sake.
if not ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1).verify_digest(signature, digest,
sigdecode=ecdsa.util.sigdecode_string):
return None
return ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1)
def _derive_y_from_x(self, x, is_even):
""" Derive y point from x point """
curve = ecdsa.SECP256k1.curve
# The curve equation over F_p is:
# y^2 = x^3 + ax + b
a, b, p = curve.a(), curve.b(), curve.p()
alpha = (pow(x, 3, p) + a * x + b) % p
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, p)
if (beta % 2) == is_even:
beta = p - beta
return beta
def compressed(self):
""" Derive compressed public key """
order = ecdsa.SECP256k1.generator.order()
p = ecdsa.VerifyingKey.from_string(bytes(self), curve=ecdsa.SECP256k1).pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
# y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
return(compressed)
def point(self):
""" Return the point for the public key """
string = unhexlify(self.unCompressed())
return ecdsa.VerifyingKey.from_string(string[1:], curve=ecdsa.SECP256k1).pubkey.point
def compressedpubkey(self):
""" Derive uncompressed public key """
secret = unhexlify(repr(self._wif))
order = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).curve.generator.order()
p = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
uncompressed = hexlify(bytes(chr(4), 'ascii') + x_str + y_str).decode('ascii')
return([compressed, uncompressed])
def recover_public_key(self, digest, signature, i):
""" Recover the public key from the the signature
"""
# See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily
curve = ecdsa.SECP256k1.curve
G = ecdsa.SECP256k1.generator
order = ecdsa.SECP256k1.order
yp = (i % 2)
r, s = ecdsa.util.sigdecode_string(signature, order)
# 1.1
x = r + (i // 2) * order
# 1.3. This actually calculates for either effectively 02||X or 03||X depending on 'k' instead of always for 02||X as specified.
# This substitutes for the lack of reversing R later on. -R actually is defined to be just flipping the y-coordinate in the elliptic curve.
alpha = ((x * x * x) + (curve.a() * x) + curve.b()) % curve.p()
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, curve.p())
y = beta if (beta - yp) % 2 == 0 else curve.p() - beta
# 1.4 Constructor of Point is supposed to check if nR is at infinity.
R = ecdsa.ellipticcurve.Point(curve, x, y, order)
# 1.5 Compute e
e = ecdsa.util.string_to_number(digest)
# 1.6 Compute Q = r^-1(sR - eG)
Q = ecdsa.numbertheory.inverse_mod(r, order) * (s * R + (-e % order) * G)
# Not strictly necessary, but let's verify the message for paranoia's sake.
if not ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1).verify_digest(signature, digest, sigdecode=ecdsa.util.sigdecode_string):
return None
return ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1)
def get_node_pk(name):
priv = ecdsa.SigningKey.from_string(sha512(name)[:32], curve=ecdsa.SECP256k1)
return priv
def get_addr_pk(name):
priv = ecdsa.SigningKey.from_string(sha512(name)[:32], curve=ecdsa.SECP256k1)
return priv
def generate_keys():
""" Gets a new elliptic curve key pair using the SECP256K1 elliptic curve (the one used by Bitcoin).
:return: elliptic curve key pair.
:rtype: list
"""
# Generate the key pair from a SECP256K1 elliptic curve.
sk = SigningKey.generate(curve=SECP256k1)
pk = sk.get_verifying_key()
return sk, pk
def sign(privkey, message):
'''??????message???'''
sk = ecdsa.SigningKey.from_string(binascii.unhexlify(privkey), curve=ecdsa.SECP256k1, hashfunc = hashlib.sha256)
signature = binascii.hexlify(sk.sign(binascii.unhexlify(message), hashfunc=hashlib.sha256))
return signature
def verify(pubkey, message, signature):
'''???? pubkey:hex pubkey, not hex_compressed'''
vk = ecdsa.VerifyingKey.from_string(binascii.unhexlify(pubkey[2:]), curve=ecdsa.SECP256k1, hashfunc = hashlib.sha256)
try:
return vk.verify(binascii.unhexlify(signature), binascii.unhexlify(message))
except ecdsa.BadSignatureError:
return False
def get_signer(curve):
if curve == NIST256p:
return NIST256pSigner
elif curve == NIST384p:
return NIST384pSigner
elif curve == SECP256k1:
return SECP256k1Signer
else:
raise Exception("Unknown curve: %s" % str(curve))
def coinbaseMessage(previous_output, receiver_address, my_address, private_key):
receiver_hashed_pubkey= base58.b58decode_check(receiver_address)[1:].encode("hex")
my_hashed_pubkey = base58.b58decode_check(my_address)[1:].encode("hex")
# Transaction stuff
version = struct.pack("<L", 1)
lock_time = struct.pack("<L", 0)
hash_code = struct.pack("<L", 1)
# Transactions input
tx_in_count = struct.pack("<B", 1)
tx_in = {}
tx_in["outpoint_hash"] = previous_output.decode('hex')[::-1]
tx_in["outpoint_index"] = struct.pack("<L", 4294967295)
tx_in["script"] = ("76a914%s88ac" % my_hashed_pubkey).decode("hex")
tx_in["script_bytes"] = struct.pack("<B", (len(tx_in["script"])))
tx_in["sequence"] = "ffffffff".decode("hex")
# Transaction output
tx_out_count = struct.pack("<B", 1)
tx_out = {}
tx_out["value"]= struct.pack("<Q", 100000000 * 12.50033629)
tx_out["pk_script"]= ("76a914%s88ac" % receiver_hashed_pubkey).decode("hex")
tx_out["pk_script_bytes"]= struct.pack("<B", (len(tx_out["pk_script"])))
tx_to_sign = (version + tx_in_count + tx_in["outpoint_hash"] + tx_in["outpoint_index"] +
tx_in["script_bytes"] + tx_in["script"] + tx_in["sequence"] + tx_out_count +
tx_out["value"] + tx_out["pk_script_bytes"] + tx_out["pk_script"] + lock_time + hash_code)
# Signing txn
hashed_raw_tx = hashlib.sha256(hashlib.sha256(tx_to_sign).digest()).digest()
sk = ecdsa.SigningKey.from_string(private_key.decode("hex"), curve = ecdsa.SECP256k1)
vk = sk.verifying_key
public_key = ('\04' + vk.to_string()).encode("hex")
sign = sk.sign_digest(hashed_raw_tx, sigencode=ecdsa.util.sigencode_der)
# Complete txn
sigscript = sign + "\01" + struct.pack("<B", len(public_key.decode("hex"))) + public_key.decode("hex")
real_tx = (version + tx_in_count + tx_in["outpoint_hash"] + tx_in["outpoint_index"] +
struct.pack("<B", (len(sigscript) + 1)) + struct.pack("<B", len(sign) + 1) + sigscript +
tx_in["sequence"] + tx_out_count + tx_out["value"] + tx_out["pk_script_bytes"] + tx_out["pk_script"] + lock_time)
return real_tx
def _derive_y_from_x(self, x, is_even):
""" Derive y point from x point """
curve = ecdsa.SECP256k1.curve
# The curve equation over F_p is:
# y^2 = x^3 + ax + b
a, b, p = curve.a(), curve.b(), curve.p()
alpha = (pow(x, 3, p) + a * x + b) % p
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, p)
if (beta % 2) == is_even:
beta = p - beta
return beta
def compressed(self):
""" Derive compressed public key """
order = ecdsa.SECP256k1.generator.order()
p = ecdsa.VerifyingKey.from_string(bytes(self), curve=ecdsa.SECP256k1).pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
# y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
return (compressed)
def point(self):
""" Return the point for the public key """
string = unhexlify(self.unCompressed())
return ecdsa.VerifyingKey.from_string(string[1:], curve=ecdsa.SECP256k1).pubkey.point
def compressedpubkey(self):
""" Derive uncompressed public key """
secret = unhexlify(repr(self._wif))
order = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).curve.generator.order()
p = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
uncompressed = hexlify(bytes(chr(4), 'ascii') + x_str + y_str).decode('ascii')
return [compressed, uncompressed]
def recover_public_key(self, digest, signature, i):
""" Recover the public key from the the signature
"""
# See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily
curve = ecdsa.SECP256k1.curve
G = ecdsa.SECP256k1.generator
order = ecdsa.SECP256k1.order
yp = (i % 2)
r, s = ecdsa.util.sigdecode_string(signature, order)
# 1.1
x = r + (i // 2) * order
# 1.3. This actually calculates for either effectively 02||X or 03||X depending on 'k' instead of always for 02||X as specified.
# This substitutes for the lack of reversing R later on. -R actually is defined to be just flipping the y-coordinate in the elliptic curve.
alpha = ((x * x * x) + (curve.a() * x) + curve.b()) % curve.p()
beta = ecdsa.numbertheory.square_root_mod_prime(alpha, curve.p())
y = beta if (beta - yp) % 2 == 0 else curve.p() - beta
# 1.4 Constructor of Point is supposed to check if nR is at infinity.
R = ecdsa.ellipticcurve.Point(curve, x, y, order)
# 1.5 Compute e
e = ecdsa.util.string_to_number(digest)
# 1.6 Compute Q = r^-1(sR - eG)
Q = ecdsa.numbertheory.inverse_mod(r, order) * (s * R + (-e % order) * G)
# Not strictly necessary, but let's verify the message for paranoia's sake.
if not ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1).verify_digest(signature, digest,
sigdecode=ecdsa.util.sigdecode_string):
return None
return ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1)
def createWallet():
keccak = sha3.keccak_256()
priv = SigningKey.generate(curve=SECP256k1)
pub = priv.get_verifying_key().to_string()
keccak.update(pub)
address = keccak.hexdigest()[24:]
return (encode_hex(priv.to_string()), address)
def __init__(self, sig, h, pubkey, curve=ecdsa.SECP256k1):
self.curve = curve # must be set before __init__ calls __load_pubkey
super(EcDsaSignature, self).__init__(sig, h, pubkey)
self.signingkey = None
self.n = self.pubkey.generator.order()
logger.debug("%r - check verifies.." % self)
assert (self.pubkey.verifies(self.h, self.sig))
logger.debug("%r - Signature is ok" % self)
test_ecdsa_key_recovery.py 文件源码
项目:ecdsa-private-key-recovery
作者: tintinweb
项目源码
文件源码
阅读 30
收藏 0
点赞 0
评论 0
def test_nonce_reuse(pub=None, curve=ecdsa.SECP256k1):
if not pub:
# default
pub = ecdsa.VerifyingKey.from_string(
"a50eb66887d03fe186b608f477d99bc7631c56e64bb3af7dc97e71b917c5b3647954da3444d33b8d1f90a0d7168b2f158a2c96db46733286619fccaafbaca6bc".decode(
"hex"), curve=curve).pubkey
# static testcase
# long r, long s, bytestr hash, pubkey obj.
sampleA = EcDsaSignature((3791300999159503489677918361931161866594575396347524089635269728181147153565,
49278124892733989732191499899232294894006923837369646645433456321810805698952),
bignum_to_hex(
765305792208265383632692154455217324493836948492122104105982244897804317926).decode(
"hex"),
pub)
sampleB = EcDsaSignature((3791300999159503489677918361931161866594575396347524089635269728181147153565,
34219161137924321997544914393542829576622483871868414202725846673961120333282),
bignum_to_hex(
23350593486085962838556474743103510803442242293209938584974526279226240784097).decode(
"hex"),
pub)
assert (sampleA.x is None) # not yet resolved
logger.debug("%r - recovering private-key from nonce reuse ..." % sampleA)
sampleA.recover_nonce_reuse(sampleB)
assert (sampleA.x is not None) # privkey recovered
assert sampleA.privkey
logger.debug("%r - Private key recovered! \n%s" % (sampleA, sampleA.export_key()))
# noinspection PyClassHasNoInit