secp256k1 extmod: new pubkey_decompress() function
This commit is contained in:
parent
40b2e871aa
commit
75d26b134f
3 changed files with 38 additions and 8 deletions
|
|
@ -197,6 +197,28 @@ static PyObject * pubkey_check(PyObject *self, PyObject *args) {
|
|||
return Py_BuildValue("I", 1);
|
||||
}
|
||||
|
||||
static PyObject * pubkey_decompress(PyObject *self, PyObject *args) {
|
||||
const unsigned char * in_pubkey_bytes;
|
||||
Py_ssize_t in_pubkey_bytes_len;
|
||||
if (!PyArg_ParseTuple(args, "y#", &in_pubkey_bytes, &in_pubkey_bytes_len)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Unable to parse extension mod arguments");
|
||||
return NULL;
|
||||
}
|
||||
secp256k1_context *ctx = create_context(1);
|
||||
secp256k1_pubkey pubkey;
|
||||
if (!pubkey_parse_with_check(ctx, &pubkey, in_pubkey_bytes, in_pubkey_bytes_len)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t pubkey_bytes_len = 65;
|
||||
unsigned char pubkey_bytes[pubkey_bytes_len];
|
||||
if (secp256k1_ec_pubkey_serialize(ctx, pubkey_bytes, &pubkey_bytes_len, &pubkey,
|
||||
SECP256K1_EC_UNCOMPRESSED) != 1) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Public key serialization failed");
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("y#", pubkey_bytes, pubkey_bytes_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns 64-byte serialized signature (r + s) plus integer recovery ID in range 0-3
|
||||
*/
|
||||
|
|
@ -396,6 +418,12 @@ static PyMethodDef secp256k1_methods[] = {
|
|||
METH_VARARGS,
|
||||
"Recover a serialized pubkey from a recoverable signature plus signed message"
|
||||
},
|
||||
{
|
||||
"pubkey_decompress",
|
||||
pubkey_decompress,
|
||||
METH_VARARGS,
|
||||
"Convert a compressed or uncompressed serialized pubkey into an uncompressed serialized pubkey"
|
||||
},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from ..addr import MMGenAddrType
|
|||
from ..key import PrivKey
|
||||
from ..protocol import CoinProtocol, init_proto
|
||||
from ..proto.btc.common import hash160, b58chk_encode, b58chk_decode
|
||||
from ..proto.secp256k1.secp256k1 import pubkey_tweak_add, pubkey_check
|
||||
from ..proto.secp256k1.secp256k1 import pubkey_tweak_add, pubkey_check, pubkey_decompress
|
||||
|
||||
from . import chainparams
|
||||
chainparams_data = chainparams.parse_data()
|
||||
|
|
@ -56,10 +56,6 @@ def compress_pubkey(pubkey_bytes):
|
|||
# see: proto.secp256k1.keygen.pubkey_format()
|
||||
return (b'\x02', b'\x03')[pubkey_bytes[-1] & 1] + pubkey_bytes[1:33]
|
||||
|
||||
def decompress_pubkey(pubkey_bytes):
|
||||
import ecdsa
|
||||
return b'\x04' + ecdsa.VerifyingKey.from_string(pubkey_bytes, curve=ecdsa.curves.SECP256k1).to_string()
|
||||
|
||||
class Bip32ExtendedKey(Lockable):
|
||||
|
||||
def __init__(self, key_b58):
|
||||
|
|
@ -73,7 +69,7 @@ class Bip32ExtendedKey(Lockable):
|
|||
|
||||
# Serialization:
|
||||
# ver_bytes | depth | par_print | idx | chaincode | serialized_key
|
||||
# 0:4 (4) | 4 (1) | 5:9 (4) | 9:13 (4) | 13:45 (32) | 45(46): 33(32)
|
||||
# 0:4 (4) | 4 (1) | 5:9 (4) | 9:13 (4) | 13:45 (32) | 45: (33), or 46: (32)
|
||||
ver_hex = key[:4].hex()
|
||||
bipnum, cp_entry = parse_version_bytes(ver_hex)
|
||||
|
||||
|
|
@ -273,7 +269,7 @@ class BipHDNode(Lockable):
|
|||
def address(self):
|
||||
return self.cfg.ag.to_addr(
|
||||
keygen_public_data(
|
||||
pubkey = self.key if self.cfg.addr_type.compressed else decompress_pubkey(self.key),
|
||||
pubkey = self.key if self.cfg.addr_type.compressed else pubkey_decompress(self.key),
|
||||
viewkey_bytes = None,
|
||||
pubkey_type = self.cfg.addr_type.pubkey_type,
|
||||
compressed = self.cfg.addr_type.compressed)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from mmgen.proto.secp256k1.secp256k1 import (
|
|||
pubkey_gen,
|
||||
pubkey_tweak_add,
|
||||
pubkey_check,
|
||||
pubkey_decompress,
|
||||
sign_msghash,
|
||||
pubkey_recover,
|
||||
verify_sig)
|
||||
|
|
@ -101,7 +102,7 @@ class unit_tests:
|
|||
return True
|
||||
|
||||
def pubkey_ops(self, name, ut):
|
||||
vmsg(' Generating pubkey, adding scalar 123456789 to pubkey:')
|
||||
vmsg(' Generating, checking, decompressing, and adding scalar to pubkey:')
|
||||
pk_addend_bytes = int.to_bytes(123456789, length=32, byteorder='big')
|
||||
|
||||
for privkey in (
|
||||
|
|
@ -126,6 +127,11 @@ class unit_tests:
|
|||
assert len(res1) == length
|
||||
assert res1 == res2
|
||||
|
||||
res3 = pubkey_decompress(res2)
|
||||
pubkey_check(res3)
|
||||
assert res3[0] == 4
|
||||
assert len(res3) == 65
|
||||
|
||||
return True
|
||||
|
||||
def pubkey_errors(self, name, ut):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue