diff --git a/pybtc/_secp256k1/module_secp256k1.c b/pybtc/_secp256k1/module_secp256k1.c index 98451bf..a579349 100644 --- a/pybtc/_secp256k1/module_secp256k1.c +++ b/pybtc/_secp256k1/module_secp256k1.c @@ -14,6 +14,94 @@ secp256k1_context *secp256k1_precomp_context_verify; static int context_exist = 0; + + + + + +static PyObject *secp256k1_secp256k1_ec_pubkey_tweak_add(PyObject *self, PyObject *args) { + Py_buffer pubkey; + Py_buffer tweak; + int flag; + if (!PyArg_ParseTuple(args,"y*y*i", &pubkey, &tweak, &flag)) { return NULL; } + secp256k1_pubkey data; + int t = secp256k1_ec_pubkey_parse(secp256k1_precomp_context_sign, &data, pubkey.buf, pubkey.len); + if (t==0) { return Py_BuildValue("b", -1); } + + t = secp256k1_ec_pubkey_tweak_add(secp256k1_context_no_precomp, &data, tweak.buf); + if (t==0) { return Py_BuildValue("b", -2); } + + size_t outl = 33; + if (flag == 1) { + outl = 33; + flag = SECP256K1_EC_COMPRESSED; + } else { + outl = 65; + flag = SECP256K1_EC_UNCOMPRESSED; + } + unsigned char pubkeyo[outl]; + t = secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp, pubkeyo, &outl, &data, flag); + if (t != 1) { return Py_BuildValue("b", 0); } + return Py_BuildValue("y#", pubkeyo, outl); + return Py_BuildValue("b", 0); +} + + + + +static PyObject *secp256k1_secp256k1_ecdsa_add_points(PyObject *self, PyObject *args) { + Py_buffer a; + Py_buffer b; + int flag; + if (!PyArg_ParseTuple(args,"y*y*i", &a, &b, &flag)) { return NULL; } + secp256k1_pubkey data[2]; + int t = secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, data, a.buf, a.len); + if (t==0) { return Py_BuildValue("b", -1); } + + t = secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, data + 1, b.buf, b.len); + if (t==0) { return Py_BuildValue("b", -1); } + secp256k1_pubkey out; + const secp256k1_pubkey* d[2]; + d[0] = &data[0]; + d[1] = &data[1]; + + t = secp256k1_ec_pubkey_combine(secp256k1_precomp_context_sign, &out, + d, 2); + + size_t outl; + if (flag == 1) { + outl = 33; + flag = SECP256K1_EC_COMPRESSED; + } else { + outl = 65; + flag = SECP256K1_EC_UNCOMPRESSED; + } + unsigned char pubkeyo[outl]; + t = secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp, pubkeyo, &outl, &out, flag); + if (t != 1) { return Py_BuildValue("b", 0); } + return Py_BuildValue("y#", pubkeyo, outl); + return Py_BuildValue("b", 0); +} + +static PyObject *secp256k1_secp256k1_ecdsa_signature_serialize_der(PyObject *self, PyObject *args) { + Py_buffer sig; + if (!PyArg_ParseTuple(args,"y*", &sig)) { return NULL; } + secp256k1_ecdsa_signature signature; + int t = secp256k1_ecdsa_signature_parse_compact(secp256k1_context_no_precomp, + &signature, + sig.buf); + if (t==0) { return Py_BuildValue("b", 0); } + unsigned char outputSer[72]; + size_t outputLen = 72; + t = secp256k1_ecdsa_signature_serialize_der(secp256k1_context_no_precomp, + outputSer, + &outputLen, + &signature); + if (t==0) { return Py_BuildValue("b", 0); } + return Py_BuildValue("y#", &outputSer, outputLen); + +} + static PyObject *secp256k1_secp256k1_nonce_rfc6979(PyObject *self, PyObject *args) { unsigned char nonce[32]; Py_buffer msg32; @@ -25,8 +113,6 @@ static PyObject *secp256k1_secp256k1_nonce_rfc6979(PyObject *self, PyObject *arg return Py_BuildValue("y#", &nonce, 32); } - - static PyObject *secp256k1_secp256k1_ecdsa_recover(PyObject *self, PyObject *args) { Py_buffer message; Py_buffer sig; @@ -77,7 +163,6 @@ static PyObject *secp256k1_secp256k1_ecdsa_recover(PyObject *self, PyObject *arg return Py_BuildValue("y#", pubkeyo, outl); } - static PyObject *secp256k1_secp256k1_ecdsa_verify(PyObject *self, PyObject *args) { Py_buffer message; Py_buffer pub; @@ -106,8 +191,6 @@ static PyObject *secp256k1_secp256k1_ecdsa_verify(PyObject *self, PyObject *args return Py_BuildValue("b", 1); } - - static PyObject *secp256k1_secp256k1_context_create(PyObject *self, PyObject *args) { if (context_exist == 0 ) { secp256k1_context *s = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); @@ -199,6 +282,9 @@ static PyMethodDef module_methods[] = { {"secp256k1_ecdsa_verify", secp256k1_secp256k1_ecdsa_verify, METH_VARARGS, "Verify signature"}, {"secp256k1_ecdsa_recover", secp256k1_secp256k1_ecdsa_recover, METH_VARARGS, "Recover public key from signature"}, {"secp256k1_nonce_rfc6979", secp256k1_secp256k1_nonce_rfc6979, METH_VARARGS, "Create rfc6979 nonce"}, + {"secp256k1_ecdsa_signature_serialize_der", secp256k1_secp256k1_ecdsa_signature_serialize_der, METH_VARARGS, "Serialize to DER"}, + {"secp256k1_ecdsa_add_points", secp256k1_secp256k1_ecdsa_add_points, METH_VARARGS, "2 points addition"}, + {"secp256k1_ec_pubkey_tweak_add", secp256k1_secp256k1_ec_pubkey_tweak_add, METH_VARARGS, "tweak addition "}, {NULL, NULL, 0, NULL} }; diff --git a/pybtc/crypto.py b/pybtc/crypto.py index 8fd2c28..e526bfc 100644 --- a/pybtc/crypto.py +++ b/pybtc/crypto.py @@ -40,6 +40,16 @@ def __secp256k1_ecdsa_recover__(signature, message, rec_id, compressed = True): def __secp256k1_nonce_rfc6979__(msg32, key32, counter): return _secp256k1.secp256k1_nonce_rfc6979(msg32, key32, counter) +def __secp256k1_ecdsa_signature_serialize_der__(raw_sig): + return _secp256k1.secp256k1_ecdsa_signature_serialize_der(raw_sig) + +def __secp256k1_ecdsa_add_points__(a, b, flag): + return _secp256k1.secp256k1_ecdsa_add_points(a, b, int(flag)) + +def __secp256k1_ec_pubkey_tweak_add__(pubkey, tweak, compressed = True): + return _secp256k1.secp256k1_ec_pubkey_tweak_add(pubkey, tweak, int(compressed)) + + if (__secp256k1_context_create__()): __secp256k1_context_randomize__() \ No newline at end of file diff --git a/pybtc/functions/bip32.py b/pybtc/functions/bip32.py index 624902a..7494d7f 100644 --- a/pybtc/functions/bip32.py +++ b/pybtc/functions/bip32.py @@ -1,12 +1,11 @@ from struct import pack -from secp256k1 import ffi, lib from pybtc.functions.key import private_to_public_key, private_key_to_wif from pybtc.functions.hash import hmac_sha512, double_sha256, hash160 from pybtc.functions.encode import (encode_base58, decode_base58_with_checksum, encode_base58_with_checksum) from pybtc.constants import * - +from pybtc.crypto import __secp256k1_ec_pubkey_tweak_add__ def create_master_xprivate_key(seed, testnet=False, base58=True, hex=False): """ @@ -145,17 +144,10 @@ def derive_child_xpublic_key(xpublic_key, i): s = hmac_sha512(c, k + pack(">L", i)) if int.from_bytes(s[:32], byteorder='big') >= ECDSA_SEC256K1_ORDER: return None - pubkey_ptr = ffi.new('secp256k1_pubkey *') - if not lib.secp256k1_ec_pubkey_parse(ECDSA_CONTEXT_VERIFY, pubkey_ptr, k, len(k)): - raise RuntimeError("secp256k1 parse public key operation failed") - if not lib.secp256k1_ec_pubkey_tweak_add(ECDSA_CONTEXT_ALL, pubkey_ptr, s[:32]): - raise RuntimeError("secp256k1 parse tweak addition operation failed") - pubkey = ffi.new('char [%d]' % 33) - outlen = ffi.new('size_t *', 33) - if not lib.secp256k1_ec_pubkey_serialize(ECDSA_CONTEXT_VERIFY, pubkey, outlen, pubkey_ptr, EC_COMPRESSED): - raise RuntimeError("secp256k1 serialize public key operation failed") - pk = bytes(ffi.buffer(pubkey, 33)) - print(len(pk)) + + pk = __secp256k1_ec_pubkey_tweak_add__(k, s[:32]) + if isinstance(pk, int): + raise RuntimeError("pubkey_tweak_add error %s" %pk) return b"".join([xpublic_key[:4], bytes([depth]), fingerprint,