mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 20:03:34 -03:00
Introduce secp256k1_pubkey_t type
This commit is contained in:
parent
4c63780710
commit
23cfa914d2
5 changed files with 216 additions and 250 deletions
|
@ -74,25 +74,70 @@ void secp256k1_context_destroy(
|
|||
secp256k1_context_t* ctx
|
||||
) SECP256K1_ARG_NONNULL(1);
|
||||
|
||||
/** Data type to hold a parsed and valid public key.
|
||||
This data type should be considered opaque to the user, and only created
|
||||
through API functions. It is not guaranteed to be compatible between
|
||||
different implementations. If you need to convert to a format suitable
|
||||
for storage or transmission, use secp256k1_ec_pubkey_serialize and
|
||||
secp256k1_ec_pubkey_parse.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char data[64];
|
||||
} secp256k1_pubkey_t;
|
||||
|
||||
/** Parse a variable-length public key into the pubkey object.
|
||||
* Returns: 1 if the public key was fully valid.
|
||||
* 0 if the public key could not be parsed or is invalid.
|
||||
* In: ctx: a secp256k1 context object.
|
||||
* input: pointer to a serialized public key
|
||||
* inputlen: length of the array pointed to by input
|
||||
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
|
||||
* parsed version of input. If not, its value is undefined.
|
||||
* This function supports parsing compressed (33 bytes, header byte 0x02 or
|
||||
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
|
||||
* byte 0x06 or 0x07) format public keys.
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
|
||||
const secp256k1_context_t* ctx,
|
||||
secp256k1_pubkey_t* pubkey,
|
||||
const unsigned char *input,
|
||||
int inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize a pubkey object into a serialized byte sequence.
|
||||
* Returns: 1 always.
|
||||
* In: ctx: a secp256k1 context object.
|
||||
* pubkey: a pointer to a secp256k1_pubkey_t containing an initialized
|
||||
* public key.
|
||||
* compressed: whether to serialize in compressed format.
|
||||
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if
|
||||
* compressed==1) byte array to place the serialized key in.
|
||||
* outputlen: a pointer to an integer which will contain the serialized
|
||||
* size.
|
||||
*/
|
||||
int secp256k1_ec_pubkey_serialize(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *output,
|
||||
int *outputlen,
|
||||
const secp256k1_pubkey_t* pubkey,
|
||||
int compressed
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Verify an ECDSA signature.
|
||||
* Returns: 1: correct signature
|
||||
* 0: incorrect signature
|
||||
* -1: invalid public key
|
||||
* -2: invalid signature
|
||||
* 0: incorrect or unparseable signature
|
||||
* In: ctx: a secp256k1 context object, initialized for verification.
|
||||
* 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
|
||||
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *sig,
|
||||
int siglen,
|
||||
const unsigned char *pubkey,
|
||||
int pubkeylen
|
||||
const secp256k1_pubkey_t *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
|
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
|
@ -124,7 +169,6 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979;
|
|||
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
|
||||
extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
|
||||
|
||||
|
||||
/** Create an ECDSA signature.
|
||||
* Returns: 1: signature created
|
||||
* 0: the nonce generation function failed, the private key was invalid, or there is not
|
||||
|
@ -202,20 +246,16 @@ int secp256k1_ecdsa_sign_compact(
|
|||
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
|
||||
* 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)
|
||||
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL)
|
||||
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL)
|
||||
* Out: pubkey: pointer to the recoved public key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *sig64,
|
||||
unsigned char *pubkey,
|
||||
int *pubkeylen,
|
||||
int compressed,
|
||||
secp256k1_pubkey_t *pubkey,
|
||||
int recid
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) 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
|
||||
|
@ -228,71 +268,18 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
|
|||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Just validate a public key.
|
||||
* Returns: 1: public key is valid
|
||||
* 0: public key is invalid
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
|
||||
* pubkeylen: length of pubkey
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *pubkey,
|
||||
int pubkeylen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||
|
||||
/** Compute the public key for a secret key.
|
||||
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* compressed: whether the computed public key should be compressed
|
||||
* seckey: pointer to a 32-byte private key (cannot be NULL)
|
||||
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
|
||||
* area to store the public key (cannot be NULL)
|
||||
* pubkeylen: pointer to int that will be updated to contains the pubkey's
|
||||
* length (cannot be NULL)
|
||||
* Out: pubkey: pointer to the created public key (cannot be NULL)
|
||||
* Returns: 1: secret was valid, public key stores
|
||||
* 0: secret was invalid, try again
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *pubkey,
|
||||
int *pubkeylen,
|
||||
const unsigned char *seckey,
|
||||
int compressed
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Compress a public key.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL)
|
||||
* Out: pubkeyout: pointer to a 33-byte array to put the compressed public key (cannot be NULL)
|
||||
* May alias pubkeyin.
|
||||
* pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL)
|
||||
* It will be updated to reflect the size of the public key in pubkeyout.
|
||||
* Returns: 0: pubkeyin was invalid
|
||||
* 1: pubkeyin was valid, and pubkeyout is its compressed version
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_compress(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *pubkeyin,
|
||||
unsigned char *pubkeyout,
|
||||
int *pubkeylen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Decompress a public key.
|
||||
* In: ctx: pointer to a context object (cannot be NULL)
|
||||
* pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL)
|
||||
* Out: pubkeyout: pointer to a 65-byte array to put the decompressed public key (cannot be NULL)
|
||||
* May alias pubkeyin.
|
||||
* pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL)
|
||||
* It will be updated to reflect the size of the public key in pubkeyout.
|
||||
* Returns: 0: pubkeyin was invalid
|
||||
* 1: pubkeyin was valid, and pubkeyout is its decompressed version
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *pubkeyin,
|
||||
unsigned char *pubkeyout,
|
||||
int *pubkeylen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
secp256k1_pubkey_t *pubkey,
|
||||
const unsigned char *seckey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Export a private key in DER format.
|
||||
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
|
@ -325,10 +312,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
|
|||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *pubkey,
|
||||
int pubkeylen,
|
||||
secp256k1_pubkey_t *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Tweak a private key by multiplying it with tweak. */
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
|
||||
|
@ -342,10 +328,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
|
|||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *pubkey,
|
||||
int pubkeylen,
|
||||
secp256k1_pubkey_t *pubkey,
|
||||
const unsigned char *tweak
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Updates the context randomization.
|
||||
* Returns: 1: randomization successfully updated
|
||||
|
|
|
@ -17,16 +17,18 @@ typedef struct {
|
|||
void bench_recover(void* arg) {
|
||||
int i;
|
||||
bench_recover_t *data = (bench_recover_t*)arg;
|
||||
unsigned char pubkey[33];
|
||||
secp256k1_pubkey_t pubkey;
|
||||
unsigned char pubkeyc[33];
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
int j;
|
||||
int pubkeylen = 33;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
|
||||
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, &pubkey, i % 2));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, 1));
|
||||
for (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. */
|
||||
data->sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
|
||||
data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,10 +26,12 @@ static void benchmark_verify(void* arg) {
|
|||
benchmark_verify_t* data = (benchmark_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_pubkey_t pubkey;
|
||||
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->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
|
||||
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, &pubkey) == (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);
|
||||
|
@ -38,6 +40,7 @@ static void benchmark_verify(void* arg) {
|
|||
|
||||
int main(void) {
|
||||
int i;
|
||||
secp256k1_pubkey_t pubkey;
|
||||
benchmark_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
@ -46,8 +49,8 @@ int main(void) {
|
|||
for (i = 0; i < 32; i++) data.key[i] = 33 + i;
|
||||
data.siglen = 72;
|
||||
secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
|
||||
data.pubkeylen = 33;
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1));
|
||||
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key));
|
||||
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1);
|
||||
|
||||
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
|
||||
|
||||
|
|
167
src/secp256k1.c
167
src/secp256k1.c
|
@ -54,11 +54,65 @@ void secp256k1_context_destroy(secp256k1_context_t* ctx) {
|
|||
free(ctx);
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
|
||||
static void secp256k1_pubkey_load(secp256k1_ge_t* ge, const secp256k1_pubkey_t* pubkey) {
|
||||
if (sizeof(secp256k1_ge_storage_t) == 64) {
|
||||
/* When the secp256k1_ge_storage_t type is exactly 64 byte, use its
|
||||
* representation inside secp256k1_pubkey_t, as conversion is very fast.
|
||||
* Note that secp256k1_pubkey_save must use the same representation. */
|
||||
secp256k1_ge_storage_t s;
|
||||
memcpy(&s, &pubkey->data[0], 64);
|
||||
secp256k1_ge_from_storage(ge, &s);
|
||||
DEBUG_CHECK(!secp256k1_fe_is_zero(&ge->x));
|
||||
} else {
|
||||
/* Otherwise, fall back to 32-byte big endian for X and Y. */
|
||||
secp256k1_fe_t x, y;
|
||||
secp256k1_fe_set_b32(&x, pubkey->data);
|
||||
DEBUG_CHECK(!secp256k1_fe_is_zero(&x));
|
||||
secp256k1_fe_set_b32(&y, pubkey->data + 32);
|
||||
secp256k1_ge_set_xy(ge, &x, &y);
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_pubkey_save(secp256k1_pubkey_t* pubkey, secp256k1_ge_t* ge) {
|
||||
if (sizeof(secp256k1_ge_storage_t) == 64) {
|
||||
secp256k1_ge_storage_t s;
|
||||
secp256k1_ge_to_storage(&s, ge);
|
||||
memcpy(&pubkey->data[0], &s, 64);
|
||||
} else {
|
||||
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
|
||||
secp256k1_fe_normalize_var(&ge->x);
|
||||
secp256k1_fe_normalize_var(&ge->y);
|
||||
secp256k1_fe_get_b32(pubkey->data, &ge->x);
|
||||
secp256k1_fe_get_b32(pubkey->data + 32, &ge->y);
|
||||
}
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t* pubkey, const unsigned char *input, int inputlen) {
|
||||
secp256k1_ge_t Q;
|
||||
|
||||
(void)ctx;
|
||||
if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
return 0;
|
||||
}
|
||||
secp256k1_pubkey_save(pubkey, &Q);
|
||||
secp256k1_ge_clear(&Q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) {
|
||||
secp256k1_ge_t Q;
|
||||
|
||||
(void)ctx;
|
||||
secp256k1_pubkey_load(&Q, pubkey);
|
||||
return secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed);
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig, int siglen, const secp256k1_pubkey_t *pubkey) {
|
||||
secp256k1_ge_t q;
|
||||
secp256k1_ecdsa_sig_t s;
|
||||
secp256k1_scalar_t m;
|
||||
int ret = -3;
|
||||
int ret = 0;
|
||||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
DEBUG_CHECK(msg32 != NULL);
|
||||
|
@ -67,19 +121,12 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *
|
|||
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
|
||||
if (secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
|
||||
if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
|
||||
if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) {
|
||||
/* success is 1, all other values are fail */
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = -2;
|
||||
secp256k1_pubkey_load(&q, pubkey);
|
||||
if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
|
||||
if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) {
|
||||
/* success is 1, all other values are fail */
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -206,7 +253,7 @@ int secp256k1_ecdsa_sign_compact(const secp256k1_context_t* ctx, const unsigned
|
|||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
|
||||
int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig64, secp256k1_pubkey_t *pubkey, int recid) {
|
||||
secp256k1_ge_t q;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t m;
|
||||
|
@ -217,7 +264,6 @@ int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsign
|
|||
DEBUG_CHECK(msg32 != NULL);
|
||||
DEBUG_CHECK(sig64 != NULL);
|
||||
DEBUG_CHECK(pubkey != NULL);
|
||||
DEBUG_CHECK(pubkeylen != NULL);
|
||||
DEBUG_CHECK(recid >= 0 && recid <= 3);
|
||||
|
||||
secp256k1_scalar_set_b32(&sig.r, sig64, &overflow);
|
||||
|
@ -226,8 +272,11 @@ int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsign
|
|||
if (!overflow) {
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
|
||||
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid)) {
|
||||
ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
|
||||
ret = secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid);
|
||||
if (ret) {
|
||||
secp256k1_pubkey_save(pubkey, &q);
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,16 +297,7 @@ int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned ch
|
|||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_verify(const secp256k1_context_t* ctx, const unsigned char *pubkey, int pubkeylen) {
|
||||
secp256k1_ge_t q;
|
||||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(pubkey != NULL);
|
||||
(void)ctx;
|
||||
|
||||
return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen);
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
|
||||
int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *seckey) {
|
||||
secp256k1_gej_t pj;
|
||||
secp256k1_ge_t p;
|
||||
secp256k1_scalar_t sec;
|
||||
|
@ -266,51 +306,20 @@ int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, unsigned char *pu
|
|||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
DEBUG_CHECK(pubkey != NULL);
|
||||
DEBUG_CHECK(pubkeylen != NULL);
|
||||
DEBUG_CHECK(seckey != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
if (!overflow) {
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
|
||||
}
|
||||
ret = !overflow & !secp256k1_scalar_is_zero(&sec);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
|
||||
secp256k1_ge_set_gej(&p, &pj);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
if (!ret) {
|
||||
*pubkeylen = 0;
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_decompress(const secp256k1_context_t* ctx, const unsigned char *pubkeyin, unsigned char *pubkeyout, int *pubkeylen) {
|
||||
secp256k1_ge_t p;
|
||||
int ret = 0;
|
||||
DEBUG_CHECK(pubkeyin != NULL);
|
||||
DEBUG_CHECK(pubkeyout != NULL);
|
||||
DEBUG_CHECK(pubkeylen != NULL);
|
||||
(void)ctx;
|
||||
|
||||
if (secp256k1_eckey_pubkey_parse(&p, pubkeyin, *pubkeylen)) {
|
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkeyout, pubkeylen, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_compress(const secp256k1_context_t* ctx, const unsigned char *pubkeyin, unsigned char *pubkeyout, int *pubkeylen) {
|
||||
secp256k1_ge_t p;
|
||||
int ret = 0;
|
||||
DEBUG_CHECK(pubkeyin != NULL);
|
||||
DEBUG_CHECK(pubkeyout != NULL);
|
||||
DEBUG_CHECK(pubkeylen != NULL);
|
||||
(void)ctx;
|
||||
|
||||
if (secp256k1_eckey_pubkey_parse(&p, pubkeyin, *pubkeylen)) {
|
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkeyout, pubkeylen, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
||||
secp256k1_scalar_t term;
|
||||
secp256k1_scalar_t sec;
|
||||
|
@ -334,7 +343,7 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char
|
|||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
|
||||
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) {
|
||||
secp256k1_ge_t p;
|
||||
secp256k1_scalar_t term;
|
||||
int ret = 0;
|
||||
|
@ -345,15 +354,13 @@ int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, unsigned char
|
|||
DEBUG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&term, tweak, &overflow);
|
||||
secp256k1_pubkey_load(&p, pubkey);
|
||||
if (!overflow) {
|
||||
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
|
||||
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);
|
||||
if (ret) {
|
||||
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);
|
||||
}
|
||||
if (ret) {
|
||||
int oldlen = pubkeylen;
|
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
|
||||
VERIFY_CHECK(pubkeylen == oldlen);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,7 +389,7 @@ int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char
|
|||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
|
||||
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) {
|
||||
secp256k1_ge_t p;
|
||||
secp256k1_scalar_t factor;
|
||||
int ret = 0;
|
||||
|
@ -393,15 +400,13 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char
|
|||
DEBUG_CHECK(tweak != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
|
||||
secp256k1_pubkey_load(&p, pubkey);
|
||||
if (!overflow) {
|
||||
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
|
||||
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);
|
||||
if (ret) {
|
||||
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);
|
||||
}
|
||||
if (ret) {
|
||||
int oldlen = pubkeylen;
|
||||
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
|
||||
VERIFY_CHECK(pubkeylen == oldlen);
|
||||
secp256k1_pubkey_save(pubkey, &p);
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
141
src/tests.c
141
src/tests.c
|
@ -1585,16 +1585,16 @@ void test_ecdsa_end_to_end(void) {
|
|||
unsigned char signature2[72];
|
||||
unsigned char signature3[72];
|
||||
unsigned char signature4[72];
|
||||
unsigned char pubkey[65];
|
||||
unsigned char recpubkey[65];
|
||||
unsigned char pubkeyc[65];
|
||||
int pubkeyclen = 65;
|
||||
secp256k1_pubkey_t pubkey;
|
||||
secp256k1_pubkey_t recpubkey;
|
||||
unsigned char seckey[300];
|
||||
int signaturelen = 72;
|
||||
int signaturelen2 = 72;
|
||||
int signaturelen3 = 72;
|
||||
int signaturelen4 = 72;
|
||||
int recid = 0;
|
||||
int recpubkeylen = 0;
|
||||
int pubkeylen = 65;
|
||||
int seckeylen = 300;
|
||||
|
||||
/* Generate a random key and message. */
|
||||
|
@ -1608,31 +1608,12 @@ void test_ecdsa_end_to_end(void) {
|
|||
|
||||
/* Construct and verify corresponding public key. */
|
||||
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, pubkey, &pubkeylen, privkey, (secp256k1_rand32() & 3) != 0) == 1);
|
||||
if (secp256k1_rand32() & 1) {
|
||||
unsigned char pubkey2[65] = {0};
|
||||
unsigned char pubkey3RE[33] = {0};
|
||||
int pubkey2len = pubkeylen, pubkey3len = pubkeylen;
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);
|
||||
|
||||
/* Decompress into a new array */
|
||||
CHECK(secp256k1_ec_pubkey_decompress(ctx, pubkey, pubkey2, &pubkey2len));
|
||||
|
||||
/* Compress into a new array */
|
||||
CHECK(secp256k1_ec_pubkey_compress(ctx, pubkey, pubkey3RE, &pubkey3len));
|
||||
|
||||
/* Check that the key was changed iff it was originally compressed */
|
||||
if (pubkeylen == 65) {
|
||||
CHECK(memcmp(pubkey, pubkey2, 65) == 0); /* Values should be the same */
|
||||
CHECK(memcmp(pubkey3RE, pubkey, 33) != 0); /* Means it should have been compressed */
|
||||
} else {
|
||||
CHECK(memcmp(pubkey, pubkey2, 65) != 0); /* Should have been decompressed */
|
||||
CHECK(memcmp(pubkey3RE, pubkey, 33) == 0); /* Therefore compressed key should equal initial pubkey */
|
||||
}
|
||||
/* Decompress in place */
|
||||
CHECK(secp256k1_ec_pubkey_decompress(ctx, pubkey, pubkey, &pubkeylen));
|
||||
CHECK(memcmp(pubkey, pubkey2, 65) == 0);
|
||||
}
|
||||
CHECK(secp256k1_ec_pubkey_verify(ctx, pubkey, pubkeylen));
|
||||
/* Verify exporting and importing public key. */
|
||||
CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand32() % 2) == 1);
|
||||
memset(&pubkey, 0, sizeof(pubkey));
|
||||
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
|
||||
|
||||
/* Verify private key import and export. */
|
||||
CHECK(secp256k1_ec_privkey_export(ctx, privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1);
|
||||
|
@ -1644,17 +1625,16 @@ void test_ecdsa_end_to_end(void) {
|
|||
int ret1;
|
||||
int ret2;
|
||||
unsigned char rnd[32];
|
||||
unsigned char pubkey2[65];
|
||||
int pubkeylen2 = 65;
|
||||
secp256k1_pubkey_t pubkey2;
|
||||
secp256k1_rand256_test(rnd);
|
||||
ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd);
|
||||
ret2 = secp256k1_ec_pubkey_tweak_add(ctx, pubkey, pubkeylen, rnd);
|
||||
ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd);
|
||||
CHECK(ret1 == ret2);
|
||||
if (ret1 == 0) {
|
||||
return;
|
||||
}
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1);
|
||||
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1);
|
||||
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
|
||||
}
|
||||
|
||||
/* Optionally tweak the keys using multiplication. */
|
||||
|
@ -1662,17 +1642,16 @@ void test_ecdsa_end_to_end(void) {
|
|||
int ret1;
|
||||
int ret2;
|
||||
unsigned char rnd[32];
|
||||
unsigned char pubkey2[65];
|
||||
int pubkeylen2 = 65;
|
||||
secp256k1_pubkey_t pubkey2;
|
||||
secp256k1_rand256_test(rnd);
|
||||
ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd);
|
||||
ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, pubkey, pubkeylen, rnd);
|
||||
ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd);
|
||||
CHECK(ret1 == ret2);
|
||||
if (ret1 == 0) {
|
||||
return;
|
||||
}
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1);
|
||||
CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0);
|
||||
CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1);
|
||||
CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0);
|
||||
}
|
||||
|
||||
/* Sign. */
|
||||
|
@ -1694,27 +1673,24 @@ void test_ecdsa_end_to_end(void) {
|
|||
CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0));
|
||||
CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0));
|
||||
/* Verify. */
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, pubkey, pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature2, signaturelen2, pubkey, pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature3, signaturelen3, pubkey, pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature4, signaturelen4, pubkey, pubkeylen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature2, signaturelen2, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature3, signaturelen3, &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature4, signaturelen4, &pubkey) == 1);
|
||||
/* Destroy signature and verify again. */
|
||||
signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, pubkey, pubkeylen) != 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) != 1);
|
||||
|
||||
/* Compact sign. */
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, message, csignature, privkey, NULL, NULL, &recid) == 1);
|
||||
CHECK(!is_empty_compact_signature(csignature));
|
||||
/* Recover. */
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1);
|
||||
CHECK(recpubkeylen == pubkeylen);
|
||||
CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0);
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) == 1);
|
||||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
|
||||
/* Destroy signature and verify again. */
|
||||
csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255);
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 ||
|
||||
memcmp(pubkey, recpubkey, pubkeylen) != 0);
|
||||
CHECK(recpubkeylen == pubkeylen);
|
||||
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) != 1 ||
|
||||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
|
||||
}
|
||||
|
||||
void test_random_pubkeys(void) {
|
||||
|
@ -1816,9 +1792,8 @@ void test_ecdsa_edge_cases(void) {
|
|||
0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86,
|
||||
0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57
|
||||
};
|
||||
unsigned char pubkey[65];
|
||||
secp256k1_pubkey_t pubkey;
|
||||
int t;
|
||||
int pubkeylen = 65;
|
||||
/* signature (r,s) = (4,4), which can be recovered with all 4 recids. */
|
||||
const unsigned char sigb64[64] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -1830,14 +1805,13 @@ void test_ecdsa_edge_cases(void) {
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
};
|
||||
unsigned char pubkeyb[33];
|
||||
int pubkeyblen = 33;
|
||||
secp256k1_pubkey_t pubkeyb;
|
||||
int recid;
|
||||
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 0));
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 1));
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 2));
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 3));
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 0));
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 1));
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 2));
|
||||
CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 3));
|
||||
|
||||
for (recid = 0; recid < 4; recid++) {
|
||||
int i;
|
||||
|
@ -1882,34 +1856,33 @@ void test_ecdsa_edge_cases(void) {
|
|||
0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E,
|
||||
0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04
|
||||
};
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, pubkeyb, &pubkeyblen, 1, recid));
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkeyb, recid));
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 1);
|
||||
for (recid2 = 0; recid2 < 4; recid2++) {
|
||||
unsigned char pubkey2b[33];
|
||||
int pubkey2blen = 33;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, pubkey2b, &pubkey2blen, 1, recid2));
|
||||
secp256k1_pubkey_t pubkey2b;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkey2b, recid2));
|
||||
/* Verifying with (order + r,4) should always fail. */
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), pubkey2b, pubkey2blen) != 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), &pubkey2b) != 1);
|
||||
}
|
||||
/* DER parsing tests. */
|
||||
/* Zero length r/s. */
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zr, sizeof(sigcder_zr), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zs, sizeof(sigcder_zs), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zr, sizeof(sigcder_zr), &pubkeyb) != 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zs, sizeof(sigcder_zs), &pubkeyb) != 1);
|
||||
/* Leading zeros. */
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt1, sizeof(sigbderalt1), pubkeyb, pubkeyblen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt2, sizeof(sigbderalt2), pubkeyb, pubkeyblen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), pubkeyb, pubkeyblen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), pubkeyb, pubkeyblen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt1, sizeof(sigbderalt1), &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt2, sizeof(sigbderalt2), &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) == 1);
|
||||
sigbderalt3[4] = 1;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) != 1);
|
||||
sigbderalt4[7] = 1;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) != 1);
|
||||
/* Damage signature. */
|
||||
sigbder[7]++;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 0);
|
||||
sigbder[7]--;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, 6, pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder)-1, pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, 6, &pubkeyb) != 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder)-1, &pubkeyb) != 1);
|
||||
for(i = 0; i < 8; i++) {
|
||||
int c;
|
||||
unsigned char orig = sigbder[i];
|
||||
|
@ -1919,8 +1892,7 @@ void test_ecdsa_edge_cases(void) {
|
|||
continue;
|
||||
}
|
||||
sigbder[i] = c;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) ==
|
||||
(i==4 || i==7) ? 0 : -2 );
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) != 1);
|
||||
}
|
||||
sigbder[i] = orig;
|
||||
}
|
||||
|
@ -1956,20 +1928,19 @@ void test_ecdsa_edge_cases(void) {
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
};
|
||||
unsigned char pubkeyc[65];
|
||||
int pubkeyclen = 65;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyc, &pubkeyclen, 0, 0) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 1);
|
||||
secp256k1_pubkey_t pubkeyc;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyc, 0) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 1);
|
||||
sigcder[4] = 0;
|
||||
sigc64[31] = 0;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0);
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0);
|
||||
sigcder[4] = 1;
|
||||
sigcder[7] = 0;
|
||||
sigc64[31] = 1;
|
||||
sigc64[63] = 0;
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0);
|
||||
CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0);
|
||||
}
|
||||
|
||||
/*Signature where s would be zero.*/
|
||||
|
|
Loading…
Reference in a new issue