Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API BREAK] Fix ECDSA message hashes to 32 bytes #150

Merged
merged 1 commit into from
Dec 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 12 additions & 20 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading