diff --git a/Makefile b/Makefile index 3d96dcb29..4e94b2f69 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ OBJS = bignum.o ecdsa.o secp256k1.o sha2.o rand.o hmac.o bip32.o ripemd160.o all: test-bip32 test-pubkey test-rfc6979 test-speed test-verify -%.o: %.c +%.o: %.c %.h $(CC) $(CFLAGS) -o $@ -c $< test-bip32: test-bip32.o $(OBJS) diff --git a/bignum.c b/bignum.c index 5abb47f1d..37b60e8f4 100644 --- a/bignum.c +++ b/bignum.c @@ -21,6 +21,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include #include "bignum.h" #include "secp256k1.h" @@ -91,7 +92,7 @@ int bn_is_less(const bignum256 *a, const bignum256 *b) return 0; } -int bn_bits(const bignum256 *a) { +int bn_bitlen(const bignum256 *a) { int i, r = 0; for (i = 0; i < 256; i++) { if (a->val[i / 30] & (1 << (i % 30))) { @@ -451,3 +452,68 @@ void bn_substract(const bignum256 *a, const bignum256 *b, bignum256 *res) temp >>= 30; } } + +// res = a - b ; a > b +void bn_substract_noprime(const bignum256 *a, const bignum256 *b, bignum256 *res) +{ + int i; + char carry = 0; + for (i = 0; i < 8; i++) { + if (a->val[i] >= b->val[i] + carry) { + res->val[i] = a->val[i] - b->val[i] - carry; + carry = 0; + } else { + res->val[i] = a->val[i] + 0x40000000 - b->val[i]; + carry = 1; + } + } + res->val[8] = a->val[8] - b->val[8] - carry; +} + +// a / 58 = q (+r) +void bn_divmod58(const bignum256 *a, bignum256 *q, uint32_t *r) +{ + bignum256 i58, rem; + int na, i; + + bn_zero(q); + bn_zero(&i58); i58.val[0] = 58; + + if (bn_is_less(a, &i58)) { + *r = a->val[0]; + } + + na = bn_bitlen(a); + + for (i = 0; i < 9; i++) { + rem.val[i] = a->val[i]; + } + + for (i = 0; i <= na - 6; i++) { + bn_lshift(&i58); + } + + for (i = na - 5; i >= 0; --i) { + bn_lshift(q); + if (!bn_is_less(&rem, &i58)) { + bn_substract_noprime(&rem, &i58, &rem); + q->val[0] |= 1; + } + bn_rshift(&i58); + } + + *r = rem.val[0]; +} + +void bn_print(const bignum256 *a) +{ + printf("%04x", a->val[8] & 0x0000FFFF); + printf("%08x", (a->val[7] << 2) | ((a->val[6] & 0x30000000) >> 28)); + printf("%07x", a->val[6] & 0x0FFFFFFF); + printf("%08x", (a->val[5] << 2) | ((a->val[4] & 0x30000000) >> 28)); + printf("%07x", a->val[4] & 0x0FFFFFFF); + printf("%08x", (a->val[3] << 2) | ((a->val[2] & 0x30000000) >> 28)); + printf("%07x", a->val[2] & 0x0FFFFFFF); + printf("%08x", (a->val[1] << 2) | ((a->val[0] & 0x30000000) >> 28)); + printf("%07x", a->val[0] & 0x0FFFFFFF); +} diff --git a/bignum.h b/bignum.h index 0e5106f77..6a59c4122 100644 --- a/bignum.h +++ b/bignum.h @@ -56,7 +56,7 @@ int bn_is_zero(const bignum256 *a); int bn_is_less(const bignum256 *a, const bignum256 *b); -int bn_bits(const bignum256 *a); +int bn_bitlen(const bignum256 *a); void bn_lshift(bignum256 *a); @@ -76,4 +76,10 @@ void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime); void bn_substract(const bignum256 *a, const bignum256 *b, bignum256 *res); +void bn_substract_noprime(const bignum256 *a, const bignum256 *b, bignum256 *res); + +void bn_divmod58(const bignum256 *a, bignum256 *q, uint32_t *r); + +void bn_print(const bignum256 *a); + #endif diff --git a/bip32.c b/bip32.c index 566a2d186..a0ba5361c 100644 --- a/bip32.c +++ b/bip32.c @@ -15,6 +15,7 @@ void xprv_from_seed(uint8_t *seed, int seed_len, xprv *out) // form a continuous 64 byte block in the memory hmac_sha512((uint8_t *)"Bitcoin seed", 12, seed, seed_len, out->private_key); ecdsa_get_public_key_compressed(out->private_key, out->public_key); + ecdsa_get_address(out->public_key, 0, out->address); } void xprv_descent(xprv *inout, uint32_t i) @@ -44,4 +45,5 @@ void xprv_descent(xprv *inout, uint32_t i) bn_write_be(&a, inout->private_key); ecdsa_get_public_key_compressed(inout->private_key, inout->public_key); + ecdsa_get_address(inout->public_key, 0, inout->address); } diff --git a/bip32.h b/bip32.h index 497f244a6..a413575f3 100644 --- a/bip32.h +++ b/bip32.h @@ -11,6 +11,7 @@ typedef struct { uint8_t private_key[32]; // private_key + chain_code have to uint8_t chain_code[32]; // form a continuous 64 byte block uint8_t public_key[33]; + char address[35]; } xprv; void xprv_from_seed(uint8_t *seed, int seed_len, xprv *out); diff --git a/ecdsa.c b/ecdsa.c index 7b33d9222..acf7a518c 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -28,6 +28,7 @@ #include "bignum.h" #include "rand.h" #include "sha2.h" +#include "ripemd160.h" #include "hmac.h" #include "ecdsa.h" @@ -338,6 +339,53 @@ void ecdsa_get_public_key_compressed(const uint8_t *priv_key, uint8_t *pub_key) bn_write_be(&R.x, pub_key + 1); } +void ecdsa_get_address(const uint8_t *pub_key, char version, char *addr) +{ + const char code[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + char *p = addr, s; + uint8_t a[32], b[21]; + uint32_t r; + bignum256 c, q; + int i, l; + + SHA256_Raw(pub_key, 33, a); + b[0] = version; + ripemd160(a, 32, b + 1); + + SHA256_Raw(b, 21, a); + SHA256_Raw(a, 32, a); + + memcpy(a + 28, a, 4); // checksum + memset(a, 0, 7); // zeroes + memcpy(a + 7, b, 21); // ripemd160(sha256(version + pubkey) + + bn_read_be(a, &c); + + while (!bn_is_zero(&c)) { + bn_divmod58(&c, &q, &r); + *p = code[r]; + p++; + for (i = 0; i < 9; i++) { + c.val[i] = q.val[i]; + } + } + + if (a[0] == 0) { + *p = '1'; + p++; + } + + *p = 0; + + l = strlen(addr); + + for (i = 0; i < l / 2; i++) { + s = addr[i]; + addr[i] = addr[l - 1 - i]; + addr[l - 1 - i] = s;; + } +} + // uses secp256k1 curve // pub_key and signature are DER encoded // msg is a data that was signed diff --git a/ecdsa.h b/ecdsa.h index 77def1712..f58a60dd7 100644 --- a/ecdsa.h +++ b/ecdsa.h @@ -32,6 +32,7 @@ void ecdsa_sign(const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint32_t *sig_len); void ecdsa_get_public_key_der(const uint8_t *priv_key, uint8_t *pub_key, uint32_t *pub_key_len); void ecdsa_get_public_key_compressed(const uint8_t *priv_key, uint8_t *pub_key); +void ecdsa_get_address(const uint8_t *pub_key, char version, char *addr); int ecdsa_verify(const uint8_t *pub_key, const uint8_t *signature, const uint8_t *msg, uint32_t msg_len); #endif diff --git a/test-bip32.c b/test-bip32.c index 3d01e06d0..261690b0f 100644 --- a/test-bip32.c +++ b/test-bip32.c @@ -33,6 +33,7 @@ void xprv_print(xprv *in) printf("chain : "); for (i = 0; i < 32; i++) printf("%02x", in->chain_code[i]); printf("\n"); printf("priv : "); for (i = 0; i < 32; i++) printf("%02x", in->private_key[i]); printf("\n"); printf("pub : "); for (i = 0; i < 33; i++) printf("%02x", in->public_key[i]); printf("\n"); + printf("addr : "); printf("%s\n", in->address); printf("\n"); } @@ -48,6 +49,7 @@ int main() printf("chain : 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508\n"); printf("priv : e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35\n"); printf("pub : 0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2\n"); + printf("addr : 15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma\n"); printf("\n"); xprv_descent_prime(&node, 0); @@ -58,6 +60,7 @@ int main() printf("chain : 47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141\n"); printf("priv : edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea\n"); printf("pub : 035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56\n"); + printf("addr : 19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh\n"); printf("\n"); xprv_descent(&node, 1); @@ -68,6 +71,7 @@ int main() printf("chain : 2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19\n"); printf("priv : 3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368\n"); printf("pub : 03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c\n"); + printf("addr : 1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj\n"); printf("\n"); return 0;