def verify_recover_secp256k1_bc_native(signature, req, hasher=coincurve.utils.sha256, context=GLOBAL_CONTEXT): # Compact native_rec_sig = ffi.new("secp256k1_ecdsa_recoverable_signature *") raw_sig, recovery_id = signature[:64], coincurve.utils.bytes_to_int( signature[64:]) lib.secp256k1_ecdsa_recoverable_signature_parse_compact( context.ctx, native_rec_sig, raw_sig, recovery_id) # Recover public key native_public_key = ffi.new("secp256k1_pubkey *") msg_hash = hasher(req) if hasher is not None else req lib.secp256k1_ecdsa_recover(context.ctx, native_public_key, native_rec_sig, msg_hash) # Convert native_standard_sig = ffi.new("secp256k1_ecdsa_signature *") lib.secp256k1_ecdsa_recoverable_signature_convert(context.ctx, native_standard_sig, native_rec_sig) # Verify ret = lib.secp256k1_ecdsa_verify(context.ctx, native_standard_sig, msg_hash, native_public_key)
def test_libsecp256k1() -> None: msg = "Satoshi Nakamoto".encode() q, _ = dsa.gen_keys(0x1) sig = dsa.sign(msg, q) msg_hash = reduce_to_hlen(msg) secret = q.to_bytes(32, "big") c_sig = ffi.new("secp256k1_ecdsa_signature *") if not lib.secp256k1_ecdsa_sign(GLOBAL_CTX, c_sig, msg_hash, secret, ffi.NULL, ffi.NULL): raise RuntimeError("libsecp256k1 signature failed") output = ffi.new("unsigned char[%d]" % CDATA_SIG_LENGTH) if not lib.secp256k1_ecdsa_signature_serialize_compact( GLOBAL_CTX, output, c_sig): raise RuntimeError("libsecp256k1 signature serialization failed") c_sig_bytes = bytes(ffi.buffer(output, CDATA_SIG_LENGTH)) r = c_sig_bytes[:32] s = c_sig_bytes[32:] assert r.hex() == sig.r.to_bytes(32, "big").hex() assert s.hex() == sig.s.to_bytes(32, "big").hex()
def quick_sign_message(message, wif, hashfn=hashlib.sha256): if not isinstance(message, bytes): message = bytes(message, "utf-8") digest = hashfn(message).digest() priv_key = QuickPrivateKey(wif) if sys.version > '3': p = bytes(priv_key) else: p = bytes(priv_key.__bytes__()) ndata = CCffi.new("const int *ndata") ndata[0] = 0 while True: ndata[0] += 1 signature = CCffi.new('secp256k1_ecdsa_recoverable_signature *') signed = CClib.secp256k1_ecdsa_sign_recoverable( CCGLOBAL_CONTEXT.ctx, signature, digest, p, CCffi.NULL, ndata) if not signed: raise AssertionError() output = CCffi.new('unsigned char[%d]' % 64) recid = CCffi.new('int *') CClib.secp256k1_ecdsa_recoverable_signature_serialize_compact( CCGLOBAL_CONTEXT.ctx, output, recid, signature) output_sig = CCffi.buffer(output, 64) if _is_canonical(output_sig): return bytes(CCutils.int_to_bytes(31 + recid[0]) + output_sig)
def generate_signature(cls, message, private_key): x = ffi.new('long long *') x[0] = random.SystemRandom().randint(0, sys.maxsize) key = PrivateKey.from_hex(private_key) signature = key.sign(message.encode('utf-8'), custom_nonce=(ffi.NULL, x)) return base64.b64encode(signature).decode('utf-8')
def generate_signature_with_private_key(cls, private_key, message): x = ffi.new('long *') x[0] = random.SystemRandom().randint(0, sys.maxint) key = PrivateKey.from_hex(private_key) signature = key.sign(message, custom_nonce=(ffi.NULL, x)) return base64.b64encode(signature)