From da3038c757935ca276fb95f476125ed34940bdfc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 5 May 2013 05:12:43 +0200 Subject: [PATCH] Privkey import/export --- include/secp256k1.h | 7 ++++ src/ecdsa.h | 2 + src/impl/ecdsa.h | 95 +++++++++++++++++++++++++++++++++++++++++++++ src/secp256k1.c | 19 +++++++++ 4 files changed, 123 insertions(+) diff --git a/include/secp256k1.h b/include/secp256k1.h index 49e22f89e3..4f3799eb04 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -90,6 +90,13 @@ int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const u int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); +int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, + unsigned char *privkey, int *privkeylen, + int compressed); + +int secp256k1_ecdsa_privkey_import(unsigned char *seckey, + const unsigned char *privkey, int privkeylen); + #ifdef __cplusplus } #endif diff --git a/src/ecdsa.h b/src/ecdsa.h index 3bb17391c3..3b4eab6f8e 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -18,5 +18,7 @@ int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid); int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); +int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); +int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); #endif diff --git a/src/impl/ecdsa.h b/src/impl/ecdsa.h index fd37e2a4ec..cef667679b 100644 --- a/src/impl/ecdsa.h +++ b/src/impl/ecdsa.h @@ -210,4 +210,99 @@ void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char } } +int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { + const unsigned char *end = privkey + privkeylen; + // sequence header + if (end < privkey+1 || *privkey != 0x30) + return 0; + privkey++; + // sequence length constructor + int lenb = 0; + if (end < privkey+1 || !(*privkey & 0x80)) + return 0; + lenb = *privkey & ~0x80; privkey++; + if (lenb < 1 || lenb > 2) + return 0; + if (end < privkey+lenb) + return 0; + // sequence length + int len = 0; + len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + privkey += lenb; + if (end < privkey+len) + return 0; + // sequence element 0: version number (=1) + if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) + return 0; + privkey += 3; + // sequence element 1: octet string, 32 bytes + if (end < privkey+34 || privkey[0] != 0x04 || privkey[1] != 0x20) + return 0; + secp256k1_num_set_bin(key, privkey+2, 32); + return 1; +} + +int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { + secp256k1_gej_t rp; + secp256k1_ecmult_gen(&rp, key); + secp256k1_ge_t r; + secp256k1_ge_set_gej(&r, &rp); + if (compressed) { + static const unsigned char begin[] = { + 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x21 + }; + static const unsigned char end[] = { + 0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,0x8C,0xD0, + 0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00,0x03,0x18,0x39,0x05,0xAE, + 0x25,0xE8,0x15,0x63,0x4C,0xE7,0xF5,0xD9,0xBE,0xDB,0xAA,0x2C,0x39,0x03,0x2A,0xB9, + 0x8C,0x75,0xB5,0xE8,0x8F,0xE4,0x3F,0x8D,0xD8,0x24,0x6F,0x3C + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_num_get_bin(ptr, 32, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; + memcpy(ptr, end, sizeof(end)); ptr += sizeof(end); + *privkeylen = ptr - privkey; + } else { + static const unsigned char begin[] = { + 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x41 + }; + static const unsigned char end[] = { + 0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,0x8C,0xD0, + 0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00,0x04,0x18,0x39,0x05,0xAE, + 0x25,0xE8,0x15,0x63,0x4C,0xE7,0xF5,0xD9,0xBE,0xDB,0xAA,0x2C,0x39,0x03,0x2A,0xB9, + 0x8C,0x75,0xB5,0xE8,0x8F,0xE4,0x3F,0x8D,0xD8,0x24,0x6F,0x3C,0x54,0x73,0xCC,0xD4, + 0xAB,0x47,0x5E,0x6A,0x9E,0x66,0x20,0xB5,0x2F,0x5C,0xE2,0xFD,0x15,0xA2,0xDE,0x32, + 0xCB,0xE9,0x05,0x15,0x4B,0x3A,0x05,0x84,0x4A,0xF7,0x07,0x85 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_num_get_bin(ptr, 32, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; + memcpy(ptr, end, sizeof(end)); ptr += sizeof(end); + *privkeylen = ptr - privkey; + } + return 1; +} + #endif diff --git a/src/secp256k1.c b/src/secp256k1.c index 0b67f7bcac..fa2272385c 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -141,3 +141,22 @@ int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0); return 1; } + +int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { + secp256k1_num_t key; + secp256k1_num_init(&key); + secp256k1_num_set_bin(&key, seckey, 32); + int ret = secp256k1_ecdsa_privkey_serialize(privkey, privkeylen, &key, compressed); + secp256k1_num_free(&key); + return ret; +} + +int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { + secp256k1_num_t key; + secp256k1_num_init(&key); + int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen); + if (ret) + secp256k1_num_get_bin(seckey, 32, &key); + secp256k1_num_free(&key); + return ret; +}