From 133c068f374871dcb84715bdd4db3dd69a2a6382 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 6 Oct 2016 16:54:07 +0200 Subject: [PATCH] Reworked rfc6979 signing. (#72) This adds an is_canonic parameter to all sign functions. This is a callback that determines if a signature corresponds to some coin specific rules. It is used, e. g., by ethereum (where the recovery byte must be 0 or 1, and not 2 or 3) and or steem signatures (which require both r and s to be between 2^248 and 2^255). This also separates the initialization and the step function of the random number generator, making it easy to restart the signature process with the next random number. --- bip32.c | 8 +- bip32.h | 4 +- ecdsa.c | 214 ++++++++++++++++++++++++------------------------- ecdsa.h | 16 ++-- test-openssl.c | 2 +- test_curves.py | 2 +- test_speed.c | 4 +- tests.c | 15 ++-- 8 files changed, 132 insertions(+), 133 deletions(-) diff --git a/bip32.c b/bip32.c index c72a672ac..de82996a3 100644 --- a/bip32.c +++ b/bip32.c @@ -415,25 +415,25 @@ int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash) // msg is a data to be signed // msg_len is the message length -int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby) +int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { if (node->curve == &ed25519_info) { hdnode_fill_public_key(node); ed25519_sign(msg, msg_len, node->private_key, node->public_key + 1, sig); return 0; } else { - return ecdsa_sign(node->curve->params, node->private_key, msg, msg_len, sig, pby); + return ecdsa_sign(node->curve->params, node->private_key, msg, msg_len, sig, pby, is_canonical); } } -int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby) +int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { if (node->curve == &ed25519_info) { hdnode_fill_public_key(node); ed25519_sign(digest, 32, node->private_key, node->public_key + 1, sig); return 0; } else { - return ecdsa_sign_digest(node->curve->params, node->private_key, digest, sig, pby); + return ecdsa_sign_digest(node->curve->params, node->private_key, digest, sig, pby, is_canonical); } } diff --git a/bip32.h b/bip32.h index fe12a1a2f..83e76797b 100644 --- a/bip32.h +++ b/bip32.h @@ -71,8 +71,8 @@ void hdnode_fill_public_key(HDNode *node); int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash); #endif -int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby); -int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby); +int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, char *str, int strsize); diff --git a/ecdsa.c b/ecdsa.c index fbde6b9a2..4e39e7105 100644 --- a/ecdsa.c +++ b/ecdsa.c @@ -614,79 +614,62 @@ void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point * #endif // generate random K for signing -int generate_k_random(const ecdsa_curve *curve, bignum256 *k) { - int i, j; - for (j = 0; j < 10000; j++) { - for (i = 0; i < 8; i++) { - k->val[i] = random32() & 0x3FFFFFFF; - } - k->val[8] = random32() & 0xFFFF; - // if k is too big or too small, we don't like it - if ( !bn_is_zero(k) && bn_is_less(k, &curve->order) ) { - return 0; // good number - no error - } +void generate_k_random(bignum256 *k) { + int i; + for (i = 0; i < 8; i++) { + k->val[i] = random32() & 0x3FFFFFFF; } - // we generated 10000 numbers, none of them is good -> fail - return 1; + k->val[8] = random32() & 0xFFFF; } -// generate K in a deterministic way, according to RFC6979 -// http://tools.ietf.org/html/rfc6979 -int generate_k_rfc6979(const ecdsa_curve *curve, bignum256 *secret, const uint8_t *priv_key, const uint8_t *hash) -{ - int i, error; - uint8_t v[32], k[32], bx[2*32], buf[32 + 1 + sizeof(bx)]; - bignum256 z1; +void init_k_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) { + uint8_t bx[2*32]; + uint8_t buf[32 + 1 + 2*32]; memcpy(bx, priv_key, 32); - bn_read_be(hash, &z1); - bn_mod(&z1, &curve->order); - bn_write_be(&z1, bx + 32); - - memset(v, 1, sizeof(v)); - memset(k, 0, sizeof(k)); - - memcpy(buf, v, sizeof(v)); - buf[sizeof(v)] = 0x00; - memcpy(buf + sizeof(v) + 1, bx, 64); - hmac_sha256(k, sizeof(k), buf, sizeof(buf), k); - hmac_sha256(k, sizeof(k), v, sizeof(v), v); - - memcpy(buf, v, sizeof(v)); - buf[sizeof(v)] = 0x01; - memcpy(buf + sizeof(v) + 1, bx, 64); - hmac_sha256(k, sizeof(k), buf, sizeof(buf), k); - hmac_sha256(k, sizeof(k), v, sizeof(v), v); - - error = 1; - for (i = 0; i < 10000; i++) { - hmac_sha256(k, sizeof(k), v, sizeof(v), v); - bn_read_be(v, secret); - if ( !bn_is_zero(secret) && bn_is_less(secret, &curve->order) ) { - error = 0; // good number -> no error - break; - } - memcpy(buf, v, sizeof(v)); - buf[sizeof(v)] = 0x00; - hmac_sha256(k, sizeof(k), buf, sizeof(v) + 1, k); - hmac_sha256(k, sizeof(k), v, sizeof(v), v); - } - // we generated 10000 numbers, none of them is good -> fail + memcpy(bx+32, hash, 32); + + memset(state->v, 1, sizeof(state->v)); + memset(state->k, 0, sizeof(state->k)); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x01; + memcpy(buf + sizeof(state->v) + 1, bx, 64); + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); - MEMSET_BZERO(v, sizeof(v)); - MEMSET_BZERO(k, sizeof(k)); MEMSET_BZERO(bx, sizeof(bx)); MEMSET_BZERO(buf, sizeof(buf)); - return error; +} + +// generate K in a deterministic way, according to RFC6979 +// http://tools.ietf.org/html/rfc6979 +void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) +{ + uint8_t buf[32 + 1]; + + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + bn_read_be(state->v, k); + memcpy(buf, state->v, sizeof(state->v)); + buf[sizeof(state->v)] = 0x00; + hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k); + hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v); + MEMSET_BZERO(buf, sizeof(buf)); } // msg is a data to be signed // msg_len is the message length -int ecdsa_sign(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby) +int ecdsa_sign(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { uint8_t hash[32]; sha256_Raw(msg, msg_len, hash); - int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby); + int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby, is_canonical); MEMSET_BZERO(hash, sizeof(hash)); return res; @@ -694,12 +677,12 @@ int ecdsa_sign(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t // msg is a data to be signed // msg_len is the message length -int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby) +int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { uint8_t hash[32]; sha256_Raw(msg, msg_len, hash); sha256_Raw(hash, 32, hash); - int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby); + int res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby, is_canonical); MEMSET_BZERO(hash, sizeof(hash)); return res; } @@ -708,82 +691,93 @@ int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const u // priv_key is a 32 byte big endian stored number // sig is 64 bytes long array for the signature // digest is 32 bytes of digest -int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby) +// is_canonical is an optional function that checks if the signature +// conforms to additional coin-specific rules. +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { - uint32_t i; + int i; curve_point R; bignum256 k, z; - bignum256 *da = &R.y; - int result = 0; + bignum256 *s = &R.y; + uint8_t by; // signature recovery byte + +#if USE_RFC6979 + rfc6979_state rng; + init_k_rfc6979(priv_key, digest, &rng); +#endif + bn_read_be(digest, &z); + for (i = 0; i < 10000; i++) { + #if USE_RFC6979 - // generate K deterministically - if (generate_k_rfc6979(curve, &k, priv_key, digest) != 0) { - result = 1; - } + // generate K deterministically + generate_k_rfc6979(&k, &rng); #else - // generate random number k - if (generate_k_random(curve, &k) != 0) { - result = 1; - } + // generate random number k + generate_k_random(&k); #endif + // if k is too big or too small, we don't like it + if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) { + continue; + } - if (result == 0) { // compute k*G scalar_multiply(curve, &k, &R); - if (pby) { - *pby = R.y.val[0] & 1; - } + by = R.y.val[0] & 1; // r = (rx mod n) if (!bn_is_less(&R.x, &curve->order)) { bn_subtract(&R.x, &curve->order, &R.x); - if (pby) { - *pby |= 2; - } + by |= 2; } - // if r is zero, we fail - if (bn_is_zero(&R.x)) - { - result = 2; + // if r is zero, we retry + if (bn_is_zero(&R.x)) { + continue; } - } - if (result == 0) { bn_inverse(&k, &curve->order); - bn_read_be(priv_key, da); - bn_multiply(&R.x, da, &curve->order); - for (i = 0; i < 8; i++) { - da->val[i] += z.val[i]; - da->val[i + 1] += (da->val[i] >> 30); - da->val[i] &= 0x3FFFFFFF; + bn_read_be(priv_key, s); + bn_multiply(&R.x, s, &curve->order); + bn_add(s, &z); + bn_multiply(&k, s, &curve->order); + bn_mod(s, &curve->order); + // if s is zero, we retry + if (bn_is_zero(s)) { + continue; } - da->val[8] += z.val[8]; - bn_multiply(da, &k, &curve->order); - bn_mod(&k, &curve->order); - // if k is zero, we fail - if (bn_is_zero(&k)) { - result = 3; - } - } - if (result == 0) { // if S > order/2 => S = -S - if (bn_is_less(&curve->order_half, &k)) { - bn_subtract(&curve->order, &k, &k); - if (pby) { - *pby ^= 1; - } + if (bn_is_less(&curve->order_half, s)) { + bn_subtract(&curve->order, s, s); + by ^= 1; } - // we are done, R.x and k is the result signature + // we are done, R.x and s is the result signature bn_write_be(&R.x, sig); - bn_write_be(&k, sig + 32); + bn_write_be(s, sig + 32); + + // check if the signature is acceptable or retry + if (is_canonical && !is_canonical(by, sig)) { + continue; + } + + if (pby) { + *pby = by; + } + + MEMSET_BZERO(&k, sizeof(k)); +#if USE_RFC6979 + MEMSET_BZERO(&rng, sizeof(rng)); +#endif + return 0; } + // Too many retries without a valid signature + // -> fail with an error MEMSET_BZERO(&k, sizeof(k)); - MEMSET_BZERO(&z, sizeof(z)); - MEMSET_BZERO(&R, sizeof(R)); - return result; +#if USE_RFC6979 + MEMSET_BZERO(&rng, sizeof(rng)); +#endif + return -1; } void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key) diff --git a/ecdsa.h b/ecdsa.h index b7c22aa4d..c0629d5d5 100644 --- a/ecdsa.h +++ b/ecdsa.h @@ -48,6 +48,11 @@ typedef struct { } ecdsa_curve; +// rfc6979 pseudo random number generator state +typedef struct { + uint8_t v[32], k[32]; +} rfc6979_state; + void point_copy(const curve_point *cp1, curve_point *cp2); void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2); void point_double(const ecdsa_curve *curve, curve_point *cp); @@ -60,9 +65,9 @@ void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point * void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y); int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed); -int ecdsa_sign(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby); -int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby); -int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby); +int ecdsa_sign(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); +int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])); void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key); void ecdsa_get_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash); @@ -80,7 +85,8 @@ int ecdsa_verify_digest_recover(const ecdsa_curve *curve, uint8_t *pub_key, cons int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der); // Private -int generate_k_rfc6979(const ecdsa_curve *curve, bignum256 *secret, const uint8_t *priv_key, const uint8_t *hash); -int generate_k_random(const ecdsa_curve *curve, bignum256 *k); +void init_k_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng); +void generate_k_rfc6979(bignum256 *k, rfc6979_state *rng); +void generate_k_random(bignum256 *k); #endif diff --git a/test-openssl.c b/test-openssl.c index cd52a0948..2af6286b7 100644 --- a/test-openssl.c +++ b/test-openssl.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) } // use our ECDSA signer to sign the message with the key - if (ecdsa_sign(CURVE, priv_key, msg, msg_len, sig, 0) != 0) { + if (ecdsa_sign(CURVE, priv_key, msg, msg_len, sig, NULL, NULL) != 0) { printf("trezor-crypto signing failed\n"); break; } diff --git a/test_curves.py b/test_curves.py index 845c41b0a..0c47dfeec 100755 --- a/test_curves.py +++ b/test_curves.py @@ -380,7 +380,7 @@ def test_sign(curve, r): digest = r.randbytes(32) sig = r.randbytes(64) - lib.ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0)) + lib.ecdsa_sign_digest(curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0)) exp = bytes2num(priv) sk = ecdsa.SigningKey.from_secret_exponent(exp, curve, diff --git a/test_speed.c b/test_speed.c index 0378692ef..23ce4dcc4 100644 --- a/test_speed.c +++ b/test_speed.c @@ -25,7 +25,7 @@ void bench_secp256k1(void) { memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); ecdsa_get_public_key33(curve, priv, pub); - ecdsa_sign(curve, priv, msg, sizeof(msg), sig, &pby); + ecdsa_sign(curve, priv, msg, sizeof(msg), sig, &pby, NULL); clock_t t = clock(); for (int i = 0 ; i < 500; i++) { @@ -42,7 +42,7 @@ void bench_nist256p1(void) { memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32); ecdsa_get_public_key33(curve, priv, pub); - ecdsa_sign(curve, priv, msg, sizeof(msg), sig, &pby); + ecdsa_sign(curve, priv, msg, sizeof(msg), sig, &pby, NULL); clock_t t = clock(); for (int i = 0 ; i < 500; i++) { diff --git a/tests.c b/tests.c index a19e76155..0eda9710e 100644 --- a/tests.c +++ b/tests.c @@ -1266,18 +1266,17 @@ END_TEST #define test_deterministic(KEY, MSG, K) do { \ sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \ - res = generate_k_rfc6979(curve, &k, fromhex(KEY), buf); \ - ck_assert_int_eq(res, 0); \ + init_k_rfc6979(fromhex(KEY), buf, &rng); \ + generate_k_rfc6979(&k, &rng); \ bn_write_be(&k, buf); \ ck_assert_mem_eq(buf, fromhex(K), 32); \ } while (0) START_TEST(test_rfc6979) { - int res; bignum256 k; uint8_t buf[32]; - const ecdsa_curve *curve = &secp256k1; + rfc6979_state rng; test_deterministic("cca9fbcc1b41e5a95d369eaa6ddcff73b61a4efaa279cfc6567e8daa39cbaf50", "sample", "2df40ca70e639d89528a6b670d9d48d9165fdc0febc0974056bdce192b8e16a3"); test_deterministic("0000000000000000000000000000000000000000000000000000000000000001", "Satoshi Nakamoto", "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15"); @@ -1303,13 +1302,13 @@ START_TEST(test_sign_speed) memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32); for (i = 0 ; i < 250; i++) { - res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, 0); + res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, NULL, NULL); ck_assert_int_eq(res, 0); } memcpy(priv_key, fromhex("509a0382ff5da48e402967a671bdcde70046d07f0df52cff12e8e3883b426a0a"), 32); for (i = 0 ; i < 250; i++) { - res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, 0); + res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, NULL, NULL); ck_assert_int_eq(res, 0); } @@ -1320,13 +1319,13 @@ START_TEST(test_sign_speed) memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32); for (i = 0 ; i < 250; i++) { - res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, 0); + res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, NULL, NULL); ck_assert_int_eq(res, 0); } memcpy(priv_key, fromhex("509a0382ff5da48e402967a671bdcde70046d07f0df52cff12e8e3883b426a0a"), 32); for (i = 0 ; i < 250; i++) { - res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, 0); + res = ecdsa_sign(curve, priv_key, msg, sizeof(msg), sig, NULL, NULL); ck_assert_int_eq(res, 0); }