mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
add function for computing addresses
This commit is contained in:
parent
1fda6fe339
commit
92f070498f
2
Makefile
2
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)
|
||||
|
68
bignum.c
68
bignum.c
@ -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);
|
||||
}
|
||||
|
8
bignum.h
8
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
|
||||
|
2
bip32.c
2
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);
|
||||
}
|
||||
|
1
bip32.h
1
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);
|
||||
|
48
ecdsa.c
48
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
|
||||
|
1
ecdsa.h
1
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
|
||||
|
@ -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…
Reference in New Issue
Block a user