def sign(self, message: bytes, hasher: Hasher = sha256, custom_nonce: Nonce = DEFAULT_NONCE) -> bytes: """ Create an ECDSA signature. :param message: The message to sign. :param hasher: The hash function to use, which must return 32 bytes. By default, the `sha256` algorithm is used. If `None`, no hashing occurs. :param custom_nonce: Custom nonce data in the form `(nonce_function, input_data)`. Refer to [secp256k1.h](https://github.com/bitcoin-core/secp256k1/blob/f8c0b57e6ba202b1ce7c5357688de97c9c067697/include/secp256k1.h#L546-L547). :return: The ECDSA signature. :raises ValueError: If the message hash was not 32 bytes long, the nonce generation function failed, or the private key was invalid. """ msg_hash = hasher(message) if hasher is not None else message if len(msg_hash) != 32: raise ValueError('Message hash must be 32 bytes long.') signature = ffi.new('secp256k1_ecdsa_signature *') nonce_fn, nonce_data = custom_nonce signed = lib.secp256k1_ecdsa_sign(self.context.ctx, signature, msg_hash, self.secret, nonce_fn, nonce_data) if not signed: raise ValueError( 'The nonce generation function failed, or the private key was invalid.' ) return cdata_to_der(signature, self.context)
def sign(self, message, hasher=sha256, custom_nonce=None): msg_hash = hasher(message) if hasher is not None else message if len(msg_hash) != 32: raise ValueError('Message hash must be 32 bytes long.') signature = ffi.new('secp256k1_ecdsa_signature *') nonce_fn, nonce_data = custom_nonce or DEFAULT_NONCE signed = lib.secp256k1_ecdsa_sign(self.context.ctx, signature, msg_hash, self.secret, nonce_fn, nonce_data) if not signed: raise ValueError('The nonce generation function failed, or the private key was invalid.') return cdata_to_der(signature, self.context)
def ecrecover_to_pub(sig, rawhash): pk = coincurve.PublicKey.from_signature_and_message(serialized_sig=sig, message=rawhash) # print(pk.format().hex()) r_sig = ecdsa.deserialize_recoverable(sig) n_sig = ecdsa.recoverable_convert(r_sig) der = ecdsa.cdata_to_der(n_sig) assert pk.verify(der, rawhash) x, y = pk.point() print('======') print(hex(x)) print(hex(y)) print('======') # return pk.format(compressed=False)[1:] return unhexlify("%064x%064x" % (x, y))
def is_signature_valid(signature, digest, public_key_bytes): signature = cdata_to_der(deserialize_compact(signature)) public_key = cPublicKey(public_key_bytes) is_valid = public_key.verify(signature, digest, None) if not is_valid: # try old way # ytsync signed claims don't seem to validate with coincurve try: pk = ec.EllipticCurvePublicKey.from_encoded_point( ec.SECP256K1(), public_key_bytes) pk.verify(signature, digest, ec.ECDSA(Prehashed(hashes.SHA256()))) return True except (ValueError, InvalidSignature): pass return is_valid
def test_der(): assert cdata_to_der(der_to_cdata(SIGNATURE)) == SIGNATURE