mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-12 18:49:07 +00:00
remove der encoding, introduce 33/65 bytes pubkeys, 64 bytes signature
This commit is contained in:
parent
58a65d9cd7
commit
896905c5c8
6
bip32.c
6
bip32.c
@ -14,7 +14,7 @@ void xprv_from_seed(uint8_t *seed, int seed_len, xprv *out)
|
||||
// this can be done because private_key[32] and chain_code[32]
|
||||
// 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_public_key33(out->private_key, out->public_key);
|
||||
ecdsa_get_address(out->public_key, 0, out->address);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ void xprv_descent(xprv *inout, uint32_t i)
|
||||
data[0] = 0;
|
||||
memcpy(data + 1, inout->private_key, 32);
|
||||
} else {
|
||||
ecdsa_get_public_key_compressed(inout->private_key, data);
|
||||
ecdsa_get_public_key33(inout->private_key, data);
|
||||
}
|
||||
write_be(data + 33, i);
|
||||
|
||||
@ -44,6 +44,6 @@ void xprv_descent(xprv *inout, uint32_t i)
|
||||
inout->child_num = i;
|
||||
bn_write_be(&a, inout->private_key);
|
||||
|
||||
ecdsa_get_public_key_compressed(inout->private_key, inout->public_key);
|
||||
ecdsa_get_public_key33(inout->private_key, inout->public_key);
|
||||
ecdsa_get_address(inout->public_key, 0, inout->address);
|
||||
}
|
||||
|
122
ecdsa.c
122
ecdsa.c
@ -135,57 +135,6 @@ void scalar_multiply(bignum256 *k, curve_point *res)
|
||||
bn_mod(&(res->y), &prime256k1);
|
||||
}
|
||||
|
||||
// does not validate that this is valid der encoding
|
||||
// assumes it is der encoding containing 1 number
|
||||
void der_read_single(const uint8_t *der, bignum256 *elem)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t val[32];
|
||||
i = 1 + der[1];
|
||||
j = 31;
|
||||
// we ignore all bytes after 32nd. if there are any, those are either zero or invalid for secp256k1
|
||||
while (i > 1 && j >= 0) {
|
||||
val[j] = der[i];
|
||||
i--; j--;
|
||||
}
|
||||
for (i = 0; i <= j; i++) {
|
||||
val[i] = 0;
|
||||
}
|
||||
bn_read_be(val, elem);
|
||||
}
|
||||
|
||||
// does not validate that this is valid der encoding
|
||||
// assumes it is der encoding containing 2 numbers (either public key or ecdsa signature)
|
||||
void der_read_pair(const uint8_t *der, bignum256 *elem1, bignum256 *elem2)
|
||||
{
|
||||
der_read_single(der + 2, elem1);
|
||||
der_read_single(der + 4 + der[3], elem2);
|
||||
}
|
||||
|
||||
// write DER encoding of number to buffer
|
||||
void der_write(const bignum256 *x, uint8_t *buf)
|
||||
{
|
||||
int i, j = 8, k = 8, len = 0;
|
||||
uint8_t r = 0, temp;
|
||||
buf[0] = 2;
|
||||
for (i = 0; i < 32; i++) {
|
||||
temp = (x->val[j] >> k) + r;
|
||||
k -= 8;
|
||||
if (k < 0) {
|
||||
r = (x->val[j]) << (-k);
|
||||
k += 30;
|
||||
j--;
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
if (len || temp) {
|
||||
buf[2 + len] = temp;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
buf[1] = len;
|
||||
}
|
||||
|
||||
// generate random K for signing
|
||||
void generate_k_random(bignum256 *k) {
|
||||
int i;
|
||||
@ -245,9 +194,8 @@ void generate_k_rfc6979(bignum256 *secret, const uint8_t *priv_key, const uint8_
|
||||
// priv_key is a 32 byte big endian stored number
|
||||
// msg is a data to be signed
|
||||
// msg_len is the message length
|
||||
// sig is at least 70 bytes long array for the signature
|
||||
// sig_len is the pointer to a uint that will contain resulting signature length. note that ((*sig_len) == sig[1]+2)
|
||||
void ecdsa_sign(const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint32_t *sig_len)
|
||||
// sig is 64 bytes long array for the signature
|
||||
void ecdsa_sign(const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t hash[32];
|
||||
@ -295,39 +243,12 @@ void ecdsa_sign(const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, u
|
||||
// we are done, R.x and k is the result signature
|
||||
break;
|
||||
}
|
||||
der_write(&R.x, sig + 2);
|
||||
i = sig[3] + 2;
|
||||
der_write(&k, sig + 2 + i);
|
||||
i += sig[3 + i] + 2;
|
||||
sig[0] = 0x30;
|
||||
sig[1] = i;
|
||||
*sig_len = i + 2;
|
||||
|
||||
bn_write_be(&R.x, sig);
|
||||
bn_write_be(&k, sig + 32);
|
||||
}
|
||||
|
||||
// uses secp256k1 curve
|
||||
// priv_key is a 32 byte big endian stored number
|
||||
// pub_key is at least 70 bytes long array for the public key
|
||||
void ecdsa_get_public_key_der(const uint8_t *priv_key, uint8_t *pub_key, uint32_t *pub_key_len)
|
||||
{
|
||||
uint32_t i;
|
||||
curve_point R;
|
||||
bignum256 k;
|
||||
|
||||
bn_read_be(priv_key, &k);
|
||||
// compute k*G
|
||||
scalar_multiply(&k, &R);
|
||||
der_write(&R.x, pub_key + 2);
|
||||
i = pub_key[3] + 2;
|
||||
der_write(&R.y, pub_key + 2 + i);
|
||||
i += pub_key[3 + i] + 2;
|
||||
pub_key[0] = 0x30;
|
||||
pub_key[1] = i;
|
||||
*pub_key_len = i + 2;
|
||||
}
|
||||
|
||||
|
||||
// pub_key is always 33 bytes long
|
||||
void ecdsa_get_public_key_compressed(const uint8_t *priv_key, uint8_t *pub_key)
|
||||
void ecdsa_get_public_key33(const uint8_t *priv_key, uint8_t *pub_key)
|
||||
{
|
||||
curve_point R;
|
||||
bignum256 k;
|
||||
@ -339,6 +260,19 @@ 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_public_key65(const uint8_t *priv_key, uint8_t *pub_key)
|
||||
{
|
||||
curve_point R;
|
||||
bignum256 k;
|
||||
|
||||
bn_read_be(priv_key, &k);
|
||||
// compute k*G
|
||||
scalar_multiply(&k, &R);
|
||||
pub_key[0] = 0x04;
|
||||
bn_write_be(&R.x, pub_key + 1);
|
||||
bn_write_be(&R.y, pub_key + 33);
|
||||
}
|
||||
|
||||
void ecdsa_get_address(const uint8_t *pub_key, char version, char *addr)
|
||||
{
|
||||
const char code[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
@ -387,12 +321,13 @@ void ecdsa_get_address(const uint8_t *pub_key, char version, char *addr)
|
||||
}
|
||||
|
||||
// uses secp256k1 curve
|
||||
// pub_key and signature are DER encoded
|
||||
// pub_key - 65 bytes uncompressed key
|
||||
// signature - 64 bytes signature
|
||||
// msg is a data that was signed
|
||||
// msg_len is the message length
|
||||
// returns 0 if verification succeeded
|
||||
// it is assumed that public key is valid otherwise calling this does not make much sense
|
||||
int ecdsa_verify(const uint8_t *pub_key, const uint8_t *signature, const uint8_t *msg, uint32_t msg_len)
|
||||
int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t hash[32];
|
||||
@ -404,14 +339,19 @@ int ecdsa_verify(const uint8_t *pub_key, const uint8_t *signature, const uint8_t
|
||||
// if double hash is required uncomment the following line:
|
||||
// SHA256_Raw(hash, 32, hash);
|
||||
|
||||
if (pub_key[0] != 0x04) return 1;
|
||||
bn_read_be(pub_key + 1, &pub.x);
|
||||
bn_read_be(pub_key + 33, &pub.y);
|
||||
|
||||
bn_read_be(sig, &r);
|
||||
bn_read_be(sig + 32, &s);
|
||||
|
||||
bn_read_be(hash, &z);
|
||||
der_read_pair(pub_key, &pub.x, &pub.y);
|
||||
der_read_pair(signature, &r, &s);
|
||||
|
||||
if (bn_is_zero(&r) ||
|
||||
bn_is_zero(&s) ||
|
||||
(!bn_is_less(&r, &order256k1)) ||
|
||||
(!bn_is_less(&s, &order256k1))) return 1;
|
||||
(!bn_is_less(&s, &order256k1))) return 2;
|
||||
|
||||
bn_inverse(&s, &order256k1); // s^-1
|
||||
bn_multiply(&s, &z, &order256k1); // z*s^-1
|
||||
@ -441,7 +381,7 @@ int ecdsa_verify(const uint8_t *pub_key, const uint8_t *signature, const uint8_t
|
||||
bn_mod(&(res.x), &order256k1);
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (res.x.val[i] != r.val[i]) {
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
8
ecdsa.h
8
ecdsa.h
@ -29,11 +29,11 @@
|
||||
#include "secp256k1.h"
|
||||
|
||||
// all functions use secp256k1 curve
|
||||
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_sign(const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig);
|
||||
void ecdsa_get_public_key33(const uint8_t *priv_key, uint8_t *pub_key);
|
||||
void ecdsa_get_public_key65(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);
|
||||
int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
||||
|
||||
void generate_k_rfc6979(bignum256 *secret, const uint8_t *priv_key, const uint8_t *hash);
|
||||
|
||||
|
@ -206,8 +206,8 @@ static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
|
||||
|
||||
if (len) {
|
||||
uint8_t sig[70], priv_key[32], msg[256];
|
||||
uint32_t sig_len, i, msg_len;
|
||||
uint8_t sig[64], priv_key[32], msg[256];
|
||||
uint32_t i, msg_len;
|
||||
|
||||
// random message len between 1 and 256
|
||||
msg_len = (random32() & 0xFF) + 1;
|
||||
@ -229,7 +229,7 @@ static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
|
||||
|
||||
// use our ECDSA signer 10 times to sign the message with the key
|
||||
for (i = 0; i < 10; i++) {
|
||||
ecdsa_sign(priv_key, msg, msg_len, sig, &sig_len);
|
||||
ecdsa_sign(priv_key, msg, msg_len, sig);
|
||||
}
|
||||
|
||||
len = sprintf(buf, "Done!\r\n");
|
||||
|
@ -32,8 +32,8 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t sig[70], pub_key[70], priv_key[32], msg[256], buffer[1000], hash[32], *p;
|
||||
uint32_t sig_len, pub_key_len, i, j, msg_len;
|
||||
uint8_t sig[64], pub_key[65], priv_key[32], msg[256], buffer[1000], hash[32], *p;
|
||||
uint32_t i, j, msg_len;
|
||||
SHA256_CTX sha256;
|
||||
EC_GROUP *ecgroup;
|
||||
int cnt = 0;
|
||||
@ -51,11 +51,11 @@ int main()
|
||||
// new ECDSA key
|
||||
EC_KEY *eckey = EC_KEY_new();
|
||||
EC_KEY_set_group(eckey, ecgroup);
|
||||
|
||||
|
||||
// generate the key
|
||||
EC_KEY_generate_key(eckey);
|
||||
p = buffer;
|
||||
// copy key to buffer
|
||||
p = buffer;
|
||||
i2d_ECPrivateKey(eckey, &p);
|
||||
|
||||
// size of the key is in buffer[8] and the key begins right after that
|
||||
@ -75,10 +75,10 @@ int main()
|
||||
}
|
||||
|
||||
// use our ECDSA signer to sign the message with the key
|
||||
ecdsa_sign(priv_key, msg, msg_len, sig, &sig_len);
|
||||
ecdsa_sign(priv_key, msg, msg_len, sig);
|
||||
|
||||
// generate public key from private key
|
||||
ecdsa_get_public_key_der(priv_key, pub_key, &pub_key_len);
|
||||
ecdsa_get_public_key65(priv_key, pub_key);
|
||||
|
||||
// use our ECDSA verifier to verify the message signature
|
||||
if (ecdsa_verify(pub_key, sig, msg, msg_len) != 0) {
|
||||
@ -87,8 +87,9 @@ int main()
|
||||
}
|
||||
|
||||
// copy signature to the OpenSSL struct
|
||||
p = sig;
|
||||
ECDSA_SIG *signature = d2i_ECDSA_SIG(NULL, (const uint8_t **)&p, sig_len);
|
||||
ECDSA_SIG *signature = ECDSA_SIG_new();
|
||||
BN_bin2bn(sig, 32, signature->r);
|
||||
BN_bin2bn(sig + 32, 32, signature->s);
|
||||
|
||||
// compute the digest of the message
|
||||
SHA256_Init(&sha256);
|
||||
|
19
tests.c
19
tests.c
@ -49,7 +49,7 @@ uint8_t *fromhex(const char *str)
|
||||
|
||||
char *tohex(const uint8_t *bin, size_t l)
|
||||
{
|
||||
static char buf[257], digits[] = "0123456789abcdef";
|
||||
static char buf[256], digits[] = "0123456789abcdef";
|
||||
size_t i;
|
||||
for (i = 0; i < l; i++) {
|
||||
buf[i*2 ] = digits[(bin[i] >> 4) & 0xF];
|
||||
@ -186,8 +186,7 @@ END_TEST
|
||||
|
||||
START_TEST(test_sign_speed)
|
||||
{
|
||||
uint8_t sig[70], priv_key[32], msg[256];
|
||||
uint32_t sig_len;
|
||||
uint8_t sig[64], priv_key[32], msg[256];
|
||||
int i;
|
||||
|
||||
memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32);
|
||||
@ -199,7 +198,7 @@ START_TEST(test_sign_speed)
|
||||
clock_t t = clock();
|
||||
for (i = 0 ; i < 500; i++) {
|
||||
// use our ECDSA signer to sign the message with the key
|
||||
ecdsa_sign(priv_key, msg, sizeof(msg), sig, &sig_len);
|
||||
ecdsa_sign(priv_key, msg, sizeof(msg), sig);
|
||||
}
|
||||
printf("Signing speed: %0.2f sig/s\n", 1.0f * i / ((float)(clock() - t) / CLOCKS_PER_SEC));
|
||||
}
|
||||
@ -207,11 +206,10 @@ END_TEST
|
||||
|
||||
START_TEST(test_verify_speed)
|
||||
{
|
||||
uint8_t sig[70], pub_key[33], msg[256];
|
||||
int i;
|
||||
|
||||
memcpy(sig, fromhex("3044022088dc0db6bc5efa762e75fbcc802af69b9f1fcdbdffce748d403f687f855556e6022010ee8035414099ac7d89cff88a3fa246d332dfa3c78d82c801394112dda039c2"), 70);
|
||||
memcpy(pub_key, fromhex("024054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a0974"), 33);
|
||||
uint8_t sig[64], pub_key[65], msg[256];
|
||||
int i, res;
|
||||
memcpy(sig, fromhex("88dc0db6bc5efa762e75fbcc802af69b9f1fcdbdffce748d403f687f855556e610ee8035414099ac7d89cff88a3fa246d332dfa3c78d82c801394112dda039c2"), 70);
|
||||
memcpy(pub_key, fromhex("044054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a09746c7083ed2097011b1223a17a644e81f59aa3de22dac119fd980b36a8ff29a244"), 65);
|
||||
|
||||
for (i = 0; i < sizeof(msg); i++) {
|
||||
msg[i] = i * 1103515245;
|
||||
@ -220,7 +218,8 @@ START_TEST(test_verify_speed)
|
||||
clock_t t = clock();
|
||||
for (i = 0 ; i < 150; i++) {
|
||||
// use our ECDSA verifier to verify the message with the key
|
||||
ecdsa_verify(pub_key, sig, msg, sizeof(msg));
|
||||
res = ecdsa_verify(pub_key, sig, msg, sizeof(msg));
|
||||
ck_assert_int_eq(res, 0);
|
||||
}
|
||||
printf("Verifying speed: %0.2f sig/s\n", 1.0f * i / ((float)(clock() - t) / CLOCKS_PER_SEC));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user