add function for computing addresses

pull/25/head
Pavol Rusnak 11 years ago
parent 1fda6fe339
commit 92f070498f

@ -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)

@ -21,6 +21,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#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);
}

@ -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

@ -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);
}

@ -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);

@ -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

@ -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

@ -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;

Loading…
Cancel
Save