338 lines
13 KiB
C
338 lines
13 KiB
C
#include <Python.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#define USE_NUM_GMP
|
|
#include "secp256k1.h"
|
|
#include "secp256k1_recovery.h"
|
|
|
|
|
|
secp256k1_context *secp256k1_precomp_context_sign;
|
|
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);
|
|
PyBuffer_Release(&pubkey);
|
|
if (t==0) { return Py_BuildValue("b", -1); }
|
|
|
|
t = secp256k1_ec_pubkey_tweak_add(secp256k1_context_no_precomp, &data, tweak.buf);
|
|
PyBuffer_Release(&tweak);
|
|
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); }
|
|
PyObject *return_value = Py_BuildValue("y#", pubkeyo, outl);
|
|
Py_DECREF(pubkeyo);
|
|
return return_value;
|
|
}
|
|
|
|
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);
|
|
PyBuffer_Release(&a);
|
|
if (t==0) { return Py_BuildValue("b", -1); }
|
|
|
|
t = secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, data + 1, b.buf, b.len);
|
|
PyBuffer_Release(&b);
|
|
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); }
|
|
PyObject *return_value = Py_BuildValue("y#", pubkeyo, outl);
|
|
Py_DECREF(pubkeyo);
|
|
return return_value;
|
|
}
|
|
|
|
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);
|
|
PyBuffer_Release(&sig);
|
|
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); }
|
|
PyObject *return_value = Py_BuildValue("y#", &outputSer, outputLen);
|
|
Py_DECREF(outputSer);
|
|
return return_value;
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_nonce_rfc6979(PyObject *self, PyObject *args) {
|
|
unsigned char nonce[32];
|
|
Py_buffer msg32;
|
|
Py_buffer key32;
|
|
unsigned int counter;
|
|
if (!PyArg_ParseTuple(args,"y*y*b", &msg32, &key32, &counter)) { return NULL; }
|
|
|
|
int r = secp256k1_nonce_function_rfc6979(nonce, msg32.buf, key32.buf, NULL, NULL, counter);
|
|
PyBuffer_Release(&msg32);
|
|
PyBuffer_Release(&key32);
|
|
if (r == 0 ) { return Py_BuildValue("b", 0); }
|
|
PyObject *return_value = Py_BuildValue("y#", &nonce, 32);
|
|
Py_DECREF(nonce);
|
|
return return_value;
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_ecdsa_recover(PyObject *self, PyObject *args) {
|
|
Py_buffer message;
|
|
Py_buffer sig;
|
|
int rec_id;
|
|
int compressed;
|
|
if (!PyArg_ParseTuple(args,"y*y*ii", &sig, &message, &rec_id, &compressed)) { return NULL; }
|
|
|
|
secp256k1_ecdsa_signature signature;
|
|
int r = secp256k1_ecdsa_signature_parse_der(secp256k1_context_no_precomp,
|
|
&signature,
|
|
sig.buf, sig.len);
|
|
PyBuffer_Release(&sig);
|
|
if (r != 1) { return Py_BuildValue("b", -1);}
|
|
|
|
|
|
unsigned char compact_sig[64] ;
|
|
r = secp256k1_ecdsa_signature_serialize_compact(secp256k1_context_no_precomp,
|
|
compact_sig,
|
|
&signature);
|
|
|
|
if (r != 1) { return Py_BuildValue("b", -1);}
|
|
|
|
secp256k1_ecdsa_recoverable_signature signature_recoverable;
|
|
r = secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_no_precomp,
|
|
&signature_recoverable,
|
|
compact_sig,
|
|
rec_id);
|
|
if (r != 1) { return Py_BuildValue("b", -2);}
|
|
|
|
secp256k1_pubkey pubkey;
|
|
r = secp256k1_ecdsa_recover(secp256k1_precomp_context_verify,
|
|
&pubkey,
|
|
&signature_recoverable, message.buf);
|
|
PyBuffer_Release(&message);
|
|
if (r != 1) { return Py_BuildValue("b", 0);}
|
|
|
|
size_t outl;
|
|
if (compressed == 1) {
|
|
outl = 33;
|
|
compressed = SECP256K1_EC_COMPRESSED;
|
|
} else {
|
|
outl = 65;
|
|
compressed = SECP256K1_EC_UNCOMPRESSED;
|
|
}
|
|
unsigned char pubkeyo[outl];
|
|
r = secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp, pubkeyo, &outl, &pubkey, compressed);
|
|
if (r != 1) {
|
|
return Py_BuildValue("b", -3);
|
|
}
|
|
PyObject *return_value = Py_BuildValue("y#", pubkeyo, outl);
|
|
Py_DECREF(pubkeyo);
|
|
return return_value;
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_ecdsa_verify(PyObject *self, PyObject *args) {
|
|
Py_buffer message;
|
|
Py_buffer pub;
|
|
Py_buffer sig;
|
|
if (!PyArg_ParseTuple(args,"y*y*y*", &sig, &pub, &message)) { return NULL; }
|
|
|
|
secp256k1_ecdsa_signature signature;
|
|
secp256k1_pubkey pubkey;
|
|
int r = secp256k1_ecdsa_signature_parse_der(secp256k1_context_no_precomp,
|
|
&signature,
|
|
sig.buf, sig.len);
|
|
PyBuffer_Release(&sig);
|
|
if (r != 1) { return Py_BuildValue("b", -1);}
|
|
|
|
r = secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp,
|
|
&pubkey,
|
|
pub.buf, pub.len);
|
|
PyBuffer_Release(&pub);
|
|
|
|
if (r != 1) { return Py_BuildValue("b", -2);}
|
|
|
|
r = secp256k1_ecdsa_verify(secp256k1_precomp_context_verify,
|
|
&signature,
|
|
message.buf,
|
|
&pubkey);
|
|
PyBuffer_Release(&message);
|
|
if (r != 1) { return Py_BuildValue("b", 0);}
|
|
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);
|
|
secp256k1_context *v = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
|
secp256k1_precomp_context_sign = s;
|
|
secp256k1_precomp_context_verify = v;
|
|
context_exist = 1;
|
|
return Py_BuildValue("b", 1);
|
|
}
|
|
return Py_BuildValue("b", 0);
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_context_randomize(PyObject *self, PyObject *args) {
|
|
Py_buffer buffer;
|
|
if (!PyArg_ParseTuple(args,"y*", &buffer)) { return NULL; }
|
|
int r = 0;
|
|
r += secp256k1_context_randomize(secp256k1_precomp_context_sign, buffer.buf);
|
|
r += secp256k1_context_randomize(secp256k1_precomp_context_sign, buffer.buf);
|
|
PyBuffer_Release(&buffer);
|
|
if (r == 2) { return Py_BuildValue("b", 1); }
|
|
else { return Py_BuildValue("b", 0); }
|
|
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_ec_pubkey_create(PyObject *self, PyObject *args) {
|
|
int flag;
|
|
Py_buffer buffer;
|
|
if (!PyArg_ParseTuple(args,"y*i", &buffer, &flag)) { return NULL; }
|
|
secp256k1_pubkey pubkey;
|
|
|
|
int r = 0;
|
|
r = secp256k1_ec_pubkey_create(secp256k1_precomp_context_sign, &pubkey, buffer.buf);
|
|
PyBuffer_Release(&buffer);
|
|
if (r != 1) {
|
|
return Py_BuildValue("b", 0);
|
|
}
|
|
size_t outl;
|
|
if (flag == 1) {
|
|
outl = 33;
|
|
flag = SECP256K1_EC_COMPRESSED;
|
|
} else {
|
|
outl = 65;
|
|
flag = SECP256K1_EC_UNCOMPRESSED;
|
|
}
|
|
unsigned char pubkeyo[outl];
|
|
|
|
r = secp256k1_ec_pubkey_serialize(secp256k1_context_no_precomp, pubkeyo, &outl, &pubkey, flag);
|
|
if (r != 1) {
|
|
return Py_BuildValue("b", 0);
|
|
}
|
|
PyObject *return_value = Py_BuildValue("y#", pubkeyo, outl);
|
|
Py_DECREF(pubkeyo);
|
|
return return_value;
|
|
}
|
|
|
|
static PyObject *secp256k1_secp256k1_ecdsa_sign(PyObject *self, PyObject *args) {
|
|
Py_buffer msg;
|
|
Py_buffer private_key;
|
|
int der_encoding;
|
|
if (!PyArg_ParseTuple(args,"y*y*b", &msg, &private_key, &der_encoding)) {
|
|
return NULL;
|
|
}
|
|
secp256k1_ecdsa_recoverable_signature signature;
|
|
int r=1;
|
|
r = secp256k1_ecdsa_sign_recoverable(secp256k1_precomp_context_sign,
|
|
&signature,
|
|
msg.buf,
|
|
private_key.buf,
|
|
NULL, NULL);
|
|
PyBuffer_Release(&private_key);
|
|
PyBuffer_Release(&msg);
|
|
if (r != 1) {
|
|
return Py_BuildValue("b", 0);
|
|
}
|
|
if (der_encoding == 0) {
|
|
PyObject *return_value = Py_BuildValue("y#", &signature, 65);
|
|
// Py_DECREF(signature);
|
|
return return_value;
|
|
} else {
|
|
unsigned char outputSer[72];
|
|
size_t outputLen = 72;
|
|
secp256k1_ecdsa_signature_serialize_der(secp256k1_context_no_precomp,
|
|
outputSer,
|
|
&outputLen,
|
|
(const secp256k1_ecdsa_signature *)&signature);
|
|
PyObject *return_value = Py_BuildValue("y#", &outputSer, outputLen);
|
|
Py_DECREF(outputSer);
|
|
return return_value;
|
|
}
|
|
}
|
|
|
|
|
|
static PyMethodDef module_methods[] = {
|
|
{"secp256k1_context_randomize", secp256k1_secp256k1_context_randomize, METH_VARARGS, "Randomize context"},
|
|
{"secp256k1_context_create", secp256k1_secp256k1_context_create, METH_VARARGS, "Returns context"},
|
|
{"secp256k1_ec_pubkey_create", secp256k1_secp256k1_ec_pubkey_create, METH_VARARGS, "Returns public key"},
|
|
{"secp256k1_ecdsa_sign", secp256k1_secp256k1_ecdsa_sign, METH_VARARGS, "Sign message"},
|
|
{"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}
|
|
};
|
|
|
|
static struct PyModuleDef _module_secp256k1 = {
|
|
PyModuleDef_HEAD_INIT,
|
|
"_secp256k1",
|
|
"...",
|
|
-1,
|
|
module_methods
|
|
};
|
|
|
|
|
|
|
|
PyMODINIT_FUNC PyInit__secp256k1(void) {
|
|
PyObject *m;
|
|
m = PyModule_Create(&_module_secp256k1);
|
|
PyModule_AddObject(m, "SECP256K1_CONTEXT_NO_PRECOMP", PyCapsule_New(&secp256k1_context_no_precomp,
|
|
"secp256k1_context", NULL));
|
|
PyModule_AddIntMacro(m, SECP256K1_CONTEXT_VERIFY);
|
|
PyModule_AddIntMacro(m, SECP256K1_CONTEXT_SIGN);
|
|
PyModule_AddIntMacro(m, SECP256K1_CONTEXT_NONE);
|
|
PyModule_AddIntMacro(m, SECP256K1_EC_COMPRESSED);
|
|
PyModule_AddIntMacro(m, SECP256K1_EC_UNCOMPRESSED);
|
|
PyModule_AddIntMacro(m, SECP256K1_TAG_PUBKEY_EVEN);
|
|
PyModule_AddIntMacro(m, SECP256K1_TAG_PUBKEY_ODD);
|
|
PyModule_AddIntMacro(m, SECP256K1_TAG_PUBKEY_UNCOMPRESSED);
|
|
PyModule_AddIntMacro(m, SECP256K1_TAG_PUBKEY_HYBRID_EVEN);
|
|
PyModule_AddIntMacro(m, SECP256K1_TAG_PUBKEY_HYBRID_ODD);
|
|
|
|
return m;
|
|
}
|
|
|