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.
pull/25/head
Jochen Hoenicke 8 years ago committed by Pavol Rusnak
parent 00413c0b6e
commit 133c068f37

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

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

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

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

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

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

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

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

Loading…
Cancel
Save