mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-12 18:49:07 +00:00
verify now supports compressed keys
This commit is contained in:
parent
dfdcdfa044
commit
74a5b04b81
56
bignum.c
56
bignum.c
@ -21,6 +21,8 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "bignum.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
@ -210,6 +212,32 @@ void bn_fast_mod(bignum256 *x, const bignum256 *prime)
|
||||
}
|
||||
}
|
||||
|
||||
// square root of x = x^((p+1)/4)
|
||||
// http://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus
|
||||
void bn_sqrt(bignum256 *x, const bignum256 *prime)
|
||||
{
|
||||
uint32_t i, j, limb;
|
||||
bignum256 res, p;
|
||||
bn_zero(&res); res.val[0] = 1;
|
||||
memcpy(&p, prime, sizeof(bignum256));
|
||||
p.val[0] += 1;
|
||||
bn_rshift(&p);
|
||||
bn_rshift(&p);
|
||||
for (i = 0; i < 9; i++) {
|
||||
limb = p.val[i];
|
||||
for (j = 0; j < 30; j++) {
|
||||
if (i == 8 && limb == 0) break;
|
||||
if (limb & 1) {
|
||||
bn_multiply(x, &res, prime);
|
||||
}
|
||||
limb >>= 1;
|
||||
bn_multiply(x, x, prime);
|
||||
}
|
||||
}
|
||||
bn_mod(&res, prime);
|
||||
memcpy(x, &res, sizeof(bignum256));
|
||||
}
|
||||
|
||||
#ifndef INVERSE_FAST
|
||||
|
||||
#ifdef USE_PRECOMPUTED_IV
|
||||
@ -221,8 +249,7 @@ void bn_inverse(bignum256 *x, const bignum256 *prime)
|
||||
{
|
||||
uint32_t i, j, limb;
|
||||
bignum256 res;
|
||||
res.val[0] = 1;
|
||||
bn_zero(&res);
|
||||
bn_zero(&res); res.val[0] = 1;
|
||||
for (i = 0; i < 9; i++) {
|
||||
limb = prime->val[i];
|
||||
// this is not enough in general but fine for secp256k1 because prime->val[0] > 1
|
||||
@ -230,10 +257,10 @@ void bn_inverse(bignum256 *x, const bignum256 *prime)
|
||||
for (j = 0; j < 30; j++) {
|
||||
if (i == 8 && limb == 0) break;
|
||||
if (limb & 1) {
|
||||
multiply(x, &res, prime);
|
||||
bn_multiply(x, &res, prime);
|
||||
}
|
||||
limb >>= 1;
|
||||
multiply(x, x, prime);
|
||||
bn_multiply(x, x, prime);
|
||||
}
|
||||
}
|
||||
bn_mod(&res, prime);
|
||||
@ -439,6 +466,12 @@ void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime)
|
||||
bn_mod(a, prime);
|
||||
}
|
||||
|
||||
void bn_addmodi(bignum256 *a, uint32_t b, const bignum256 *prime) {
|
||||
a->val[0] += b;
|
||||
bn_normalize(a);
|
||||
bn_mod(a, prime);
|
||||
}
|
||||
|
||||
// res = a - b
|
||||
// b < 2*prime; result not normalized
|
||||
void bn_substract(const bignum256 *a, const bignum256 *b, bignum256 *res)
|
||||
@ -503,3 +536,18 @@ void bn_divmod58(const bignum256 *a, bignum256 *q, uint32_t *r)
|
||||
|
||||
*r = rem.val[0];
|
||||
}
|
||||
|
||||
#if 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);
|
||||
}
|
||||
#endif
|
||||
|
8
bignum.h
8
bignum.h
@ -68,16 +68,24 @@ void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime);
|
||||
|
||||
void bn_fast_mod(bignum256 *x, const bignum256 *prime);
|
||||
|
||||
void bn_sqrt(bignum256 *x, const bignum256 *prime);
|
||||
|
||||
void bn_inverse(bignum256 *x, const bignum256 *prime);
|
||||
|
||||
void bn_normalize(bignum256 *a);
|
||||
|
||||
void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime);
|
||||
|
||||
void bn_addmodi(bignum256 *a, uint32_t 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);
|
||||
|
||||
#if 0
|
||||
void bn_print(const bignum256 *a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
21
ecdsa.c
21
ecdsa.c
@ -339,9 +339,24 @@ int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg,
|
||||
// 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);
|
||||
if (pub_key[0] == 0x04) {
|
||||
bn_read_be(pub_key + 1, &pub.x);
|
||||
bn_read_be(pub_key + 33, &pub.y);
|
||||
} else
|
||||
if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords
|
||||
// y^2 = x^3 + 0*x + 7
|
||||
bn_read_be(pub_key + 1, &pub.x);
|
||||
bn_read_be(pub_key + 1, &pub.y); // y is x
|
||||
bn_multiply(&pub.x, &pub.y, &prime256k1); // y is x^2
|
||||
bn_multiply(&pub.x, &pub.y, &prime256k1); // y is x^3
|
||||
bn_addmodi(&pub.y, 7, &prime256k1); // y is x^3 + 7
|
||||
bn_sqrt(&pub.y, &prime256k1); // y = sqrt(y)
|
||||
if ((pub_key[0] & 0x01) != (pub.y.val[0] & 1)) {
|
||||
bn_substract(&prime256k1, &pub.y, &pub.y); // y = -y
|
||||
bn_mod(&pub.y, &prime256k1);
|
||||
}
|
||||
} else
|
||||
return 1;
|
||||
|
||||
bn_read_be(sig, &r);
|
||||
bn_read_be(sig + 32, &s);
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t sig[64], pub_key[65], priv_key[32], msg[256], buffer[1000], hash[32], *p;
|
||||
uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256], buffer[1000], hash[32], *p;
|
||||
uint32_t i, j, msg_len;
|
||||
SHA256_CTX sha256;
|
||||
EC_GROUP *ecgroup;
|
||||
@ -78,11 +78,16 @@ int main()
|
||||
ecdsa_sign(priv_key, msg, msg_len, sig);
|
||||
|
||||
// generate public key from private key
|
||||
ecdsa_get_public_key65(priv_key, pub_key);
|
||||
ecdsa_get_public_key33(priv_key, pub_key33);
|
||||
ecdsa_get_public_key65(priv_key, pub_key65);
|
||||
|
||||
// use our ECDSA verifier to verify the message signature
|
||||
if (ecdsa_verify(pub_key, sig, msg, msg_len) != 0) {
|
||||
printf("MicroECDSA verification failed\n");
|
||||
if (ecdsa_verify(pub_key65, sig, msg, msg_len) != 0) {
|
||||
printf("MicroECDSA verification failed (pub_key_len = 65)\n");
|
||||
break;
|
||||
}
|
||||
if (ecdsa_verify(pub_key33, sig, msg, msg_len) != 0) {
|
||||
printf("MicroECDSA verification failed (pub_key_len = 33)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
48
tests.c
48
tests.c
@ -49,12 +49,13 @@ uint8_t *fromhex(const char *str)
|
||||
|
||||
char *tohex(const uint8_t *bin, size_t l)
|
||||
{
|
||||
static char buf[256], digits[] = "0123456789abcdef";
|
||||
static char buf[257], digits[] = "0123456789abcdef";
|
||||
size_t i;
|
||||
for (i = 0; i < l; i++) {
|
||||
buf[i*2 ] = digits[(bin[i] >> 4) & 0xF];
|
||||
buf[i*2+1] = digits[bin[i] & 0xF];
|
||||
}
|
||||
buf[l * 2] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -189,39 +190,60 @@ START_TEST(test_sign_speed)
|
||||
uint8_t sig[64], priv_key[32], msg[256];
|
||||
int i;
|
||||
|
||||
memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32);
|
||||
|
||||
for (i = 0; i < sizeof(msg); i++) {
|
||||
msg[i] = i * 1103515245;
|
||||
}
|
||||
|
||||
clock_t t = clock();
|
||||
for (i = 0 ; i < 500; i++) {
|
||||
// use our ECDSA signer to sign the message with the key
|
||||
|
||||
memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32);
|
||||
for (i = 0 ; i < 250; i++) {
|
||||
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));
|
||||
|
||||
memcpy(priv_key, fromhex("509a0382ff5da48e402967a671bdcde70046d07f0df52cff12e8e3883b426a0a"), 32);
|
||||
for (i = 0 ; i < 250; i++) {
|
||||
ecdsa_sign(priv_key, msg, sizeof(msg), sig);
|
||||
}
|
||||
|
||||
printf("Signing speed: %0.2f sig/s\n", 500.0f / ((float)(clock() - t) / CLOCKS_PER_SEC));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_verify_speed)
|
||||
{
|
||||
uint8_t sig[64], pub_key[65], msg[256];
|
||||
uint8_t sig[64], pub_key33[33], pub_key65[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;
|
||||
}
|
||||
|
||||
clock_t t = clock();
|
||||
for (i = 0 ; i < 150; i++) {
|
||||
// use our ECDSA verifier to verify the message with the key
|
||||
res = ecdsa_verify(pub_key, sig, msg, sizeof(msg));
|
||||
|
||||
memcpy(sig, fromhex("88dc0db6bc5efa762e75fbcc802af69b9f1fcdbdffce748d403f687f855556e610ee8035414099ac7d89cff88a3fa246d332dfa3c78d82c801394112dda039c2"), 64);
|
||||
memcpy(pub_key33, fromhex("024054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a0974"), 33);
|
||||
memcpy(pub_key65, fromhex("044054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a09746c7083ed2097011b1223a17a644e81f59aa3de22dac119fd980b36a8ff29a244"), 65);
|
||||
|
||||
for (i = 0 ; i < 50; i++) {
|
||||
res = ecdsa_verify(pub_key65, sig, msg, sizeof(msg));
|
||||
ck_assert_int_eq(res, 0);
|
||||
res = ecdsa_verify(pub_key33, 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));
|
||||
|
||||
memcpy(sig, fromhex("067040a2adb3d9deefeef95dae86f69671968a0b90ee72c2eab54369612fd524eb6756c5a1bb662f1175a5fa888763cddc3a07b8a045ef6ab358d8d5d1a9a745"), 64);
|
||||
memcpy(pub_key33, fromhex("03ff45a5561a76be930358457d113f25fac790794ec70317eff3b97d7080d45719"), 33);
|
||||
memcpy(pub_key65, fromhex("04ff45a5561a76be930358457d113f25fac790794ec70317eff3b97d7080d457196235193a15778062ddaa44aef7e6901b781763e52147f2504e268b2d572bf197"), 65);
|
||||
|
||||
for (i = 0 ; i < 50; i++) {
|
||||
res = ecdsa_verify(pub_key65, sig, msg, sizeof(msg));
|
||||
ck_assert_int_eq(res, 0);
|
||||
res = ecdsa_verify(pub_key33, sig, msg, sizeof(msg));
|
||||
ck_assert_int_eq(res, 0);
|
||||
}
|
||||
|
||||
printf("Verifying speed: %0.2f sig/s\n", 200.0f / ((float)(clock() - t) / CLOCKS_PER_SEC));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user