Skip to content

Commit

Permalink
Merge pull request bitcoin#150
Browse files Browse the repository at this point in the history
cf7b2b4 Fix ECDSA message hashes to 32 bytes (Pieter Wuille)
  • Loading branch information
sipa committed Dec 11, 2014
2 parents 2a53a47 + cf7b2b4 commit bccaf86
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 86 deletions.
32 changes: 12 additions & 20 deletions include/secp256k1.h
Expand Up @@ -62,28 +62,25 @@ void secp256k1_stop(void);
* 0: incorrect signature
* -1: invalid public key
* -2: invalid signature
* In: msg: the message being verified (cannot be NULL)
* msglen: the length of the message (at most 32)
* In: msg32: the 32-byte message hash being verified (cannot be NULL)
* sig: the signature being verified (cannot be NULL)
* siglen: the length of the signature
* pubkey: the public key to verify with (cannot be NULL)
* pubkeylen: the length of pubkey
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
const unsigned char *msg,
int msglen,
const unsigned char *msg32,
const unsigned char *sig,
int siglen,
const unsigned char *pubkey,
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);

/** Create an ECDSA signature.
* Returns: 1: signature created
* 0: nonce invalid, try another one
* In: msg: the message being signed (cannot be NULL)
* msglen: the length of the message being signed (at most 32)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
* nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
Expand All @@ -92,39 +89,35 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign(
const unsigned char *msg,
int msglen,
const unsigned char *msg32,
unsigned char *sig,
int *siglen,
const unsigned char *seckey,
const unsigned char *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Create a compact ECDSA signature (64 byte + recovery id).
* Returns: 1: signature created
* 0: nonce invalid, try another one
* In: msg: the message being signed (cannot be NULL)
* msglen: the length of the message being signed (at most 32)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
* nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact(
const unsigned char *msg,
int msglen,
const unsigned char *msg32,
unsigned char *sig64,
const unsigned char *seckey,
const unsigned char *nonce,
int *recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Recover an ECDSA public key from a compact signature.
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* In: msg: the message assumed to be signed (cannot be NULL)
* msglen: the length of the message (at most 32)
* In: msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* sig64: signature as 64 byte array (cannot be NULL)
* compressed: whether to recover a compressed or uncompressed pubkey
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact)
Expand All @@ -133,14 +126,13 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact(
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
const unsigned char *msg,
int msglen,
const unsigned char *msg32,
const unsigned char *sig64,
unsigned char *pubkey,
int *pubkeylen,
int compressed,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
Expand Down
2 changes: 1 addition & 1 deletion src/bench_recover.c
Expand Up @@ -19,7 +19,7 @@ void bench_recover(void* arg) {
unsigned char pubkey[33];
for (int i=0; i<20000; i++) {
int pubkeylen = 33;
CHECK(secp256k1_ecdsa_recover_compact(data->msg, 32, data->sig, pubkey, &pubkeylen, 1, i % 2));
CHECK(secp256k1_ecdsa_recover_compact(data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
for (int j = 0; j < 32; j++) {
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
data->msg[j] = data->sig[j]; /* Move former R to message. */
Expand Down
2 changes: 1 addition & 1 deletion src/bench_sign.c
Expand Up @@ -28,7 +28,7 @@ static void bench_sign(void* arg) {
unsigned char sig[64];
for (int i=0; i<20000; i++) {
int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(data->msg, 32, sig, data->key, data->nonce, &recid));
CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, data->nonce, &recid));
for (int j = 0; j < 32; j++) {
data->nonce[j] = data->key[j]; /* Move former key to nonce */
data->msg[j] = sig[j]; /* Move former R to message. */
Expand Down
4 changes: 2 additions & 2 deletions src/bench_verify.c
Expand Up @@ -28,7 +28,7 @@ static void benchmark_verify(void* arg) {
data->sig[data->siglen - 1] ^= (i & 0xFF);
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
CHECK(secp256k1_ecdsa_verify(data->msg, 32, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
CHECK(secp256k1_ecdsa_verify(data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
data->sig[data->siglen - 1] ^= (i & 0xFF);
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
Expand All @@ -44,7 +44,7 @@ int main(void) {
for (int i = 0; i < 32; i++) data.key[i] = 33 + i;
for (int i = 0; i < 32; i++) data.nonce[i] = 65 + i;
data.siglen = 72;
CHECK(secp256k1_ecdsa_sign(data.msg, 32, data.sig, &data.siglen, data.key, data.nonce));
CHECK(secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, data.nonce));
data.pubkeylen = 33;
CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1));

Expand Down
38 changes: 10 additions & 28 deletions src/secp256k1.c
Expand Up @@ -40,15 +40,12 @@ void secp256k1_stop(void) {
secp256k1_fe_stop();
}

int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig != NULL);
DEBUG_CHECK(pubkey != NULL);

unsigned char msg32[32] = {0};
memcpy(msg32 + 32 - msglen, msg, msglen);
int ret = -3;
secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t s;
Expand All @@ -72,10 +69,9 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned
return ret;
}

int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) {
int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(signature != NULL);
DEBUG_CHECK(signaturelen != NULL);
DEBUG_CHECK(seckey != NULL);
Expand All @@ -85,12 +81,7 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
secp256k1_scalar_set_b32(&sec, seckey, NULL);
int overflow = 0;
secp256k1_scalar_set_b32(&non, nonce, &overflow);
{
unsigned char c[32] = {0};
memcpy(c + 32 - messagelen, message, messagelen);
secp256k1_scalar_set_b32(&msg, c, NULL);
memset(c, 0, 32);
}
secp256k1_scalar_set_b32(&msg, msg32, NULL);
int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
secp256k1_ecdsa_sig_t sig;
if (ret) {
Expand All @@ -105,10 +96,9 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
return ret;
}

int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(nonce != NULL);
Expand All @@ -117,12 +107,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
secp256k1_scalar_set_b32(&sec, seckey, NULL);
int overflow = 0;
secp256k1_scalar_set_b32(&non, nonce, &overflow);
{
unsigned char c[32] = {0};
memcpy(c + 32 - messagelen, message, messagelen);
secp256k1_scalar_set_b32(&msg, c, NULL);
memset(c, 0, 32);
}
secp256k1_scalar_set_b32(&msg, msg32, NULL);
int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
secp256k1_ecdsa_sig_t sig;
if (ret) {
Expand All @@ -138,18 +123,15 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
return ret;
}

int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(recid >= 0 && recid <= 3);

int ret = 0;
unsigned char msg32[32] = {0};
memcpy(msg32 + 32 - msglen, msg, msglen);
secp256k1_scalar_t m;
secp256k1_ecdsa_sig_t sig;
int overflow = 0;
Expand Down

0 comments on commit bccaf86

Please sign in to comment.