Merge pull request #282
18c329c
Remove the internal secp256k1_ecdsa_sig_t type (Pieter Wuille)74a2acd
Add a secp256k1_ecdsa_signature_t type (Pieter Wuille)23cfa91
Introduce secp256k1_pubkey_t type (Pieter Wuille)
This commit is contained in:
commit
c33307495b
|
@ -74,26 +74,148 @@ 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);
|
||||
|
||||
/** Data type to hold a parsed ECDSA signature, optionally supporting pubkey
|
||||
* recovery.
|
||||
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_ecdsa_signature_serialize_* and
|
||||
secp256k1_ecdsa_signature_parse_* functions. */
|
||||
typedef struct {
|
||||
unsigned char data[65];
|
||||
} secp256k1_ecdsa_signature_t;
|
||||
|
||||
/** Parse a DER ECDSA signature.
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise.
|
||||
* In: ctx: a secp256k1 context object
|
||||
* input: a pointer to the signature to be parsed
|
||||
* inputlen: the length of the array pointed to be input
|
||||
* Out: sig: a pointer to a signature object
|
||||
*
|
||||
* Note that this function also supports some violations of DER.
|
||||
*
|
||||
* The resulting signature object will not support pubkey recovery.
|
||||
*/
|
||||
int secp256k1_ecdsa_signature_parse_der(
|
||||
const secp256k1_context_t* ctx,
|
||||
secp256k1_ecdsa_signature_t* sig,
|
||||
const unsigned char *input,
|
||||
int inputlen
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Parse a compact ECDSA signature (64 bytes + recovery id).
|
||||
* Returns: 1 when the signature could be parsed, 0 otherwise
|
||||
* In: ctx: a secp256k1 context object
|
||||
* input64: a pointer to a 64-byte compact signature
|
||||
* recid: the recovery id (0, 1, 2 or 3, or -1 for unknown)
|
||||
* Out: sig: a pointer to a signature object
|
||||
*
|
||||
* If recid is not -1, the resulting signature object will support pubkey
|
||||
* recovery.
|
||||
*/
|
||||
int secp256k1_ecdsa_signature_parse_compact(
|
||||
const secp256k1_context_t* ctx,
|
||||
secp256k1_ecdsa_signature_t* sig,
|
||||
const unsigned char *input64,
|
||||
int recid
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||
|
||||
/** Serialize an ECDSA signature in DER format.
|
||||
* Returns: 1 if enough space was available to serialize, 0 otherwise
|
||||
* In: ctx: a secp256k1 context object
|
||||
* sig: a pointer to an initialized signature object
|
||||
* Out: output: a pointer to an array to store the DER serialization
|
||||
* In/Out: outputlen: a pointer to a length integer. Initially, this integer
|
||||
* should be set to the length of output. After the call
|
||||
* it will be set to the length of the serialization (even
|
||||
* if 0 was returned).
|
||||
*/
|
||||
int secp256k1_ecdsa_signature_serialize_der(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *output,
|
||||
int *outputlen,
|
||||
const secp256k1_ecdsa_signature_t* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
|
||||
* Returns: 1
|
||||
* In: ctx: a secp256k1 context object
|
||||
* sig: a pointer to an initialized signature object (cannot be NULL)
|
||||
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
|
||||
* recid: a pointer to an integer to hold the recovery id (can be NULL).
|
||||
*
|
||||
* If recid is not NULL, the signature must support pubkey recovery.
|
||||
*/
|
||||
int secp256k1_ecdsa_signature_serialize_compact(
|
||||
const secp256k1_context_t* ctx,
|
||||
unsigned char *output64,
|
||||
int *recid,
|
||||
const secp256k1_ecdsa_signature_t* sig
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) 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
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
|
||||
const secp256k1_ecdsa_signature_t *sig,
|
||||
const secp256k1_pubkey_t *pubkey
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
|
||||
|
||||
/** A pointer to a function to deterministically generate a nonce.
|
||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
|
||||
|
@ -124,19 +246,17 @@ 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
|
||||
* enough space in the signature (as indicated by siglen).
|
||||
* 0: the nonce generation function failed, or the private key was invalid.
|
||||
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
|
||||
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
|
||||
* to contain the actual signature length (<=72).
|
||||
*
|
||||
* The resulting signature will support pubkey recovery.
|
||||
*
|
||||
* The sig always has an s value in the lower half of the range (From 0x1
|
||||
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
|
||||
|
@ -167,55 +287,26 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
|
|||
int secp256k1_ecdsa_sign(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *msg32,
|
||||
unsigned char *sig,
|
||||
int *siglen,
|
||||
secp256k1_ecdsa_signature_t *sig,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function_t noncefp,
|
||||
const void *ndata
|
||||
) 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: the nonce generation function failed, or the secret key was invalid.
|
||||
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
|
||||
* msg32: the 32-byte message hash being signed (cannot be NULL)
|
||||
* seckey: pointer to a 32-byte secret key (cannot be NULL)
|
||||
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
|
||||
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
|
||||
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
|
||||
* In case 0 is returned, the returned signature length will be zero.
|
||||
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
|
||||
*/
|
||||
int secp256k1_ecdsa_sign_compact(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *msg32,
|
||||
unsigned char *sig64,
|
||||
const unsigned char *seckey,
|
||||
secp256k1_nonce_function_t noncefp,
|
||||
const void *ndata,
|
||||
int *recid
|
||||
) 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.
|
||||
/** Recover an ECDSA public key from a signature.
|
||||
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
|
||||
* 0: otherwise.
|
||||
* 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)
|
||||
* sig64: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
|
||||
* Out: pubkey: pointer to the recoved public key (cannot be NULL)
|
||||
*/
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
|
||||
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
|
||||
const secp256k1_context_t* ctx,
|
||||
const unsigned char *msg32,
|
||||
const unsigned char *sig64,
|
||||
unsigned char *pubkey,
|
||||
int *pubkeylen,
|
||||
int compressed,
|
||||
int recid
|
||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
|
||||
const secp256k1_ecdsa_signature_t *sig,
|
||||
secp256k1_pubkey_t *pubkey
|
||||
) 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 +319,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 +363,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 +379,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,20 @@ 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));
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(data->ctx, &sig, data->sig, i % 2));
|
||||
CHECK(secp256k1_ecdsa_recover(data->ctx, data->msg, &sig, &pubkey));
|
||||
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). */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,9 @@ static void bench_sign(void* arg) {
|
|||
for (i = 0; i < 20000; i++) {
|
||||
int j;
|
||||
int recid = 0;
|
||||
CHECK(secp256k1_ecdsa_sign_compact(data->ctx, data->msg, sig, data->key, NULL, NULL, &recid));
|
||||
secp256k1_ecdsa_signature_t signature;
|
||||
CHECK(secp256k1_ecdsa_sign(data->ctx, data->msg, &signature, data->key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_compact(data->ctx, sig, &recid, &signature));
|
||||
for (j = 0; j < 32; j++) {
|
||||
data->msg[j] = sig[j]; /* Move former R to message. */
|
||||
data->key[j] = sig[j + 32]; /* Move former S to key. */
|
||||
|
|
|
@ -26,10 +26,14 @@ static void benchmark_verify(void* arg) {
|
|||
benchmark_verify_t* data = (benchmark_verify_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_pubkey_t pubkey;
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
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_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, &sig, &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 +42,8 @@ static void benchmark_verify(void* arg) {
|
|||
|
||||
int main(void) {
|
||||
int i;
|
||||
secp256k1_pubkey_t pubkey;
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
benchmark_verify_t data;
|
||||
|
||||
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
@ -45,9 +51,10 @@ int main(void) {
|
|||
for (i = 0; i < 32; i++) data.msg[i] = 1 + i;
|
||||
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_ecdsa_sign(data.ctx, data.msg, &sig, data.key, NULL, NULL));
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig));
|
||||
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);
|
||||
|
||||
|
|
14
src/ecdsa.h
14
src/ecdsa.h
|
@ -11,14 +11,10 @@
|
|||
#include "group.h"
|
||||
#include "ecmult.h"
|
||||
|
||||
typedef struct {
|
||||
secp256k1_scalar_t r, s;
|
||||
} secp256k1_ecdsa_sig_t;
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *r, secp256k1_scalar_t *s, const unsigned char *sig, int size);
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s);
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,7 @@ static const secp256k1_fe_t secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_C
|
|||
0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
|
||||
);
|
||||
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
|
||||
static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *rr, secp256k1_scalar_t *rs, const unsigned char *sig, int size) {
|
||||
unsigned char ra[32] = {0}, sa[32] = {0};
|
||||
const unsigned char *rp;
|
||||
const unsigned char *sp;
|
||||
|
@ -98,26 +98,27 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch
|
|||
memcpy(ra + 32 - lenr, rp, lenr);
|
||||
memcpy(sa + 32 - lens, sp, lens);
|
||||
overflow = 0;
|
||||
secp256k1_scalar_set_b32(&r->r, ra, &overflow);
|
||||
secp256k1_scalar_set_b32(rr, ra, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&r->s, sa, &overflow);
|
||||
secp256k1_scalar_set_b32(rs, sa, &overflow);
|
||||
if (overflow) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
|
||||
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t* ar, const secp256k1_scalar_t* as) {
|
||||
unsigned char r[33] = {0}, s[33] = {0};
|
||||
unsigned char *rp = r, *sp = s;
|
||||
int lenR = 33, lenS = 33;
|
||||
secp256k1_scalar_get_b32(&r[1], &a->r);
|
||||
secp256k1_scalar_get_b32(&s[1], &a->s);
|
||||
secp256k1_scalar_get_b32(&r[1], ar);
|
||||
secp256k1_scalar_get_b32(&s[1], as);
|
||||
while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; }
|
||||
while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; }
|
||||
if (*size < 6+lenS+lenR) {
|
||||
*size = 6 + lenS + lenR;
|
||||
return 0;
|
||||
}
|
||||
*size = 6 + lenS + lenR;
|
||||
|
@ -132,26 +133,26 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
|
||||
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t *sigs, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
|
||||
unsigned char c[32];
|
||||
secp256k1_scalar_t sn, u1, u2;
|
||||
secp256k1_fe_t xr;
|
||||
secp256k1_gej_t pubkeyj;
|
||||
secp256k1_gej_t pr;
|
||||
|
||||
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_inverse_var(&sn, &sig->s);
|
||||
secp256k1_scalar_inverse_var(&sn, sigs);
|
||||
secp256k1_scalar_mul(&u1, &sn, message);
|
||||
secp256k1_scalar_mul(&u2, &sn, &sig->r);
|
||||
secp256k1_scalar_mul(&u2, &sn, sigr);
|
||||
secp256k1_gej_set_ge(&pubkeyj, pubkey);
|
||||
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
|
||||
if (secp256k1_gej_is_infinity(&pr)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_scalar_get_b32(c, &sig->r);
|
||||
secp256k1_scalar_get_b32(c, sigr);
|
||||
secp256k1_fe_set_b32(&xr, c);
|
||||
|
||||
/** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n)
|
||||
|
@ -186,7 +187,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, con
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
|
||||
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t* sigs, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
|
||||
unsigned char brx[32];
|
||||
secp256k1_fe_t fx;
|
||||
secp256k1_ge_t x;
|
||||
|
@ -194,11 +195,11 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co
|
|||
secp256k1_scalar_t rn, u1, u2;
|
||||
secp256k1_gej_t qj;
|
||||
|
||||
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256k1_scalar_get_b32(brx, &sig->r);
|
||||
secp256k1_scalar_get_b32(brx, sigr);
|
||||
VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */
|
||||
if (recid & 2) {
|
||||
if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) {
|
||||
|
@ -210,16 +211,16 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co
|
|||
return 0;
|
||||
}
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_scalar_inverse_var(&rn, &sig->r);
|
||||
secp256k1_scalar_inverse_var(&rn, sigr);
|
||||
secp256k1_scalar_mul(&u1, &rn, message);
|
||||
secp256k1_scalar_negate(&u1, &u1);
|
||||
secp256k1_scalar_mul(&u2, &rn, &sig->s);
|
||||
secp256k1_scalar_mul(&u2, &rn, sigs);
|
||||
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej_var(pubkey, &qj);
|
||||
return !secp256k1_gej_is_infinity(&qj);
|
||||
}
|
||||
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
|
||||
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t *sigr, secp256k1_scalar_t *sigs, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
|
||||
unsigned char b[32];
|
||||
secp256k1_gej_t rp;
|
||||
secp256k1_ge_t r;
|
||||
|
@ -231,8 +232,8 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s
|
|||
secp256k1_fe_normalize(&r.x);
|
||||
secp256k1_fe_normalize(&r.y);
|
||||
secp256k1_fe_get_b32(b, &r.x);
|
||||
secp256k1_scalar_set_b32(&sig->r, b, &overflow);
|
||||
if (secp256k1_scalar_is_zero(&sig->r)) {
|
||||
secp256k1_scalar_set_b32(sigr, b, &overflow);
|
||||
if (secp256k1_scalar_is_zero(sigr)) {
|
||||
/* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
|
@ -241,18 +242,18 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s
|
|||
if (recid) {
|
||||
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
}
|
||||
secp256k1_scalar_mul(&n, &sig->r, seckey);
|
||||
secp256k1_scalar_mul(&n, sigr, seckey);
|
||||
secp256k1_scalar_add(&n, &n, message);
|
||||
secp256k1_scalar_inverse(&sig->s, nonce);
|
||||
secp256k1_scalar_mul(&sig->s, &sig->s, &n);
|
||||
secp256k1_scalar_inverse(sigs, nonce);
|
||||
secp256k1_scalar_mul(sigs, sigs, &n);
|
||||
secp256k1_scalar_clear(&n);
|
||||
secp256k1_gej_clear(&rp);
|
||||
secp256k1_ge_clear(&r);
|
||||
if (secp256k1_scalar_is_zero(&sig->s)) {
|
||||
if (secp256k1_scalar_is_zero(sigs)) {
|
||||
return 0;
|
||||
}
|
||||
if (secp256k1_scalar_is_high(&sig->s)) {
|
||||
secp256k1_scalar_negate(&sig->s, &sig->s);
|
||||
if (secp256k1_scalar_is_high(sigs)) {
|
||||
secp256k1_scalar_negate(sigs, sigs);
|
||||
if (recid) {
|
||||
*recid ^= 1;
|
||||
}
|
||||
|
|
352
src/secp256k1.c
352
src/secp256k1.c
|
@ -54,11 +54,159 @@ 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);
|
||||
}
|
||||
|
||||
static void secp256k1_ecdsa_signature_load(secp256k1_scalar_t* r, secp256k1_scalar_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) {
|
||||
if (sizeof(secp256k1_scalar_t) == 32) {
|
||||
/* When the secp256k1_scalar_t type is exactly 32 byte, use its
|
||||
* representation inside secp256k1_ecdsa_signature_t, as conversion is very fast.
|
||||
* Note that secp256k1_ecdsa_signature_save must use the same representation. */
|
||||
memcpy(r, &sig->data[0], 32);
|
||||
memcpy(s, &sig->data[32], 32);
|
||||
} else {
|
||||
secp256k1_scalar_set_b32(r, &sig->data[0], NULL);
|
||||
secp256k1_scalar_set_b32(s, &sig->data[32], NULL);
|
||||
}
|
||||
if (recid) {
|
||||
*recid = sig->data[64];
|
||||
}
|
||||
}
|
||||
|
||||
static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, int recid) {
|
||||
if (sizeof(secp256k1_scalar_t) == 32) {
|
||||
memcpy(&sig->data[0], r, 32);
|
||||
memcpy(&sig->data[32], s, 32);
|
||||
} else {
|
||||
secp256k1_scalar_get_b32(&sig->data[0], r);
|
||||
secp256k1_scalar_get_b32(&sig->data[32], s);
|
||||
}
|
||||
sig->data[64] = recid;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) {
|
||||
secp256k1_scalar_t r, s;
|
||||
|
||||
(void)ctx;
|
||||
DEBUG_CHECK(sig != NULL);
|
||||
DEBUG_CHECK(input != NULL);
|
||||
|
||||
if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) {
|
||||
secp256k1_ecdsa_signature_save(sig, &r, &s, -1);
|
||||
return 1;
|
||||
} else {
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input64, int recid) {
|
||||
secp256k1_scalar_t r, s;
|
||||
int ret = 1;
|
||||
int overflow = 0;
|
||||
|
||||
(void)ctx;
|
||||
DEBUG_CHECK(sig != NULL);
|
||||
DEBUG_CHECK(input64 != NULL);
|
||||
|
||||
secp256k1_scalar_set_b32(&r, &input64[0], &overflow);
|
||||
ret &= !overflow;
|
||||
secp256k1_scalar_set_b32(&s, &input64[32], &overflow);
|
||||
ret &= !overflow;
|
||||
ret &= (recid == -1 || (recid >= 0 && recid < 4));
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_signature_save(sig, &r, &s, recid);
|
||||
} else {
|
||||
memset(sig, 0, sizeof(*sig));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) {
|
||||
secp256k1_scalar_t r, s;
|
||||
|
||||
(void)ctx;
|
||||
DEBUG_CHECK(output != NULL);
|
||||
DEBUG_CHECK(outputlen != NULL);
|
||||
DEBUG_CHECK(sig != NULL);
|
||||
|
||||
secp256k1_ecdsa_signature_load(&r, &s, NULL, sig);
|
||||
return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s);
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context_t* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_signature_t* sig) {
|
||||
secp256k1_scalar_t r, s;
|
||||
int rec;
|
||||
|
||||
(void)ctx;
|
||||
DEBUG_CHECK(output64 != NULL);
|
||||
DEBUG_CHECK(sig != NULL);
|
||||
|
||||
secp256k1_ecdsa_signature_load(&r, &s, &rec, sig);
|
||||
secp256k1_scalar_get_b32(&output64[0], &r);
|
||||
secp256k1_scalar_get_b32(&output64[32], &s);
|
||||
if (recid) {
|
||||
DEBUG_CHECK(rec >= 0 && rec < 4);
|
||||
*recid = rec;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *sig, const secp256k1_pubkey_t *pubkey) {
|
||||
secp256k1_ge_t q;
|
||||
secp256k1_ecdsa_sig_t s;
|
||||
secp256k1_scalar_t r, s;
|
||||
secp256k1_scalar_t m;
|
||||
int ret = -3;
|
||||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
DEBUG_CHECK(msg32 != NULL);
|
||||
|
@ -66,23 +214,9 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *
|
|||
DEBUG_CHECK(pubkey != NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
secp256k1_pubkey_load(&q, pubkey);
|
||||
secp256k1_ecdsa_signature_load(&r, &s, NULL, sig);
|
||||
return secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m);
|
||||
}
|
||||
|
||||
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
|
||||
|
@ -110,9 +244,10 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
|
|||
const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
|
||||
const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979;
|
||||
|
||||
int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, secp256k1_ecdsa_signature_t *signature, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
|
||||
secp256k1_scalar_t r, s;
|
||||
secp256k1_scalar_t sec, non, msg;
|
||||
int recid;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
unsigned int count = 0;
|
||||
|
@ -120,7 +255,6 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms
|
|||
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
DEBUG_CHECK(msg32 != NULL);
|
||||
DEBUG_CHECK(signature != NULL);
|
||||
DEBUG_CHECK(signaturelen != NULL);
|
||||
DEBUG_CHECK(seckey != NULL);
|
||||
if (noncefp == NULL) {
|
||||
noncefp = secp256k1_nonce_function_default;
|
||||
|
@ -139,99 +273,45 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms
|
|||
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
||||
memset(nonce32, 0, 32);
|
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
|
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, NULL)) {
|
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (ret) {
|
||||
ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
|
||||
}
|
||||
secp256k1_scalar_clear(&msg);
|
||||
secp256k1_scalar_clear(&non);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
}
|
||||
if (!ret) {
|
||||
*signaturelen = 0;
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_signature_save(signature, &r, &s, recid);
|
||||
} else {
|
||||
memset(signature, 0, sizeof(*signature));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_sign_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) {
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t sec, non, msg;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
unsigned int count = 0;
|
||||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||
DEBUG_CHECK(msg32 != NULL);
|
||||
DEBUG_CHECK(sig64 != NULL);
|
||||
DEBUG_CHECK(seckey != NULL);
|
||||
if (noncefp == NULL) {
|
||||
noncefp = secp256k1_nonce_function_default;
|
||||
}
|
||||
|
||||
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
|
||||
/* Fail if the secret key is invalid. */
|
||||
if (!overflow && !secp256k1_scalar_is_zero(&sec)) {
|
||||
secp256k1_scalar_set_b32(&msg, msg32, NULL);
|
||||
while (1) {
|
||||
unsigned char nonce32[32];
|
||||
ret = noncefp(nonce32, msg32, seckey, count, noncedata);
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
|
||||
memset(nonce32, 0, 32);
|
||||
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
|
||||
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, recid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (ret) {
|
||||
secp256k1_scalar_get_b32(sig64, &sig.r);
|
||||
secp256k1_scalar_get_b32(sig64 + 32, &sig.s);
|
||||
}
|
||||
secp256k1_scalar_clear(&msg);
|
||||
secp256k1_scalar_clear(&non);
|
||||
secp256k1_scalar_clear(&sec);
|
||||
}
|
||||
if (!ret) {
|
||||
memset(sig64, 0, 64);
|
||||
}
|
||||
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(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *signature, secp256k1_pubkey_t *pubkey) {
|
||||
secp256k1_ge_t q;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t r, s;
|
||||
secp256k1_scalar_t m;
|
||||
int ret = 0;
|
||||
int overflow = 0;
|
||||
int recid;
|
||||
DEBUG_CHECK(ctx != NULL);
|
||||
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
|
||||
DEBUG_CHECK(msg32 != NULL);
|
||||
DEBUG_CHECK(sig64 != NULL);
|
||||
DEBUG_CHECK(signature != NULL);
|
||||
DEBUG_CHECK(pubkey != NULL);
|
||||
DEBUG_CHECK(pubkeylen != NULL);
|
||||
DEBUG_CHECK(recid >= 0 && recid <= 3);
|
||||
|
||||
secp256k1_scalar_set_b32(&sig.r, sig64, &overflow);
|
||||
if (!overflow) {
|
||||
secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow);
|
||||
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);
|
||||
}
|
||||
}
|
||||
secp256k1_ecdsa_signature_load(&r, &s, &recid, signature);
|
||||
DEBUG_CHECK(recid >= 0 && recid < 4);
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) {
|
||||
secp256k1_pubkey_save(pubkey, &q);
|
||||
return 1;
|
||||
} else {
|
||||
memset(pubkey, 0, sizeof(*pubkey));
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) {
|
||||
|
@ -248,16 +328,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 +337,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 +374,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 +385,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 +420,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 +431,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
378
src/tests.c
378
src/tests.c
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "secp256k1.c"
|
||||
#include "testrand_impl.h"
|
||||
|
||||
|
@ -110,7 +111,7 @@ void run_context_tests(void) {
|
|||
secp256k1_gej_t pubj;
|
||||
secp256k1_ge_t pub;
|
||||
secp256k1_scalar_t msg, key, nonce;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t sigr, sigs;
|
||||
|
||||
/*** clone and destroy all of them to make sure cloning was complete ***/
|
||||
{
|
||||
|
@ -131,15 +132,15 @@ void run_context_tests(void) {
|
|||
/* obtain a working nonce */
|
||||
do {
|
||||
random_scalar_order_test(&nonce);
|
||||
} while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
|
||||
} while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
|
||||
|
||||
/* try signing */
|
||||
CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
|
||||
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL));
|
||||
CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
|
||||
CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
|
||||
|
||||
/* try verifying */
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sig, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sig, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
|
||||
/* cleanup */
|
||||
secp256k1_context_destroy(none);
|
||||
|
@ -1487,11 +1488,11 @@ void run_ecmult_gen_blind(void) {
|
|||
}
|
||||
|
||||
|
||||
void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) {
|
||||
void random_sign(secp256k1_scalar_t *sigr, secp256k1_scalar_t *sigs, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) {
|
||||
secp256k1_scalar_t nonce;
|
||||
do {
|
||||
random_scalar_order_test(&nonce);
|
||||
} while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sig, key, msg, &nonce, recid));
|
||||
} while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid));
|
||||
}
|
||||
|
||||
void test_ecdsa_sign_verify(void) {
|
||||
|
@ -1499,7 +1500,7 @@ void test_ecdsa_sign_verify(void) {
|
|||
secp256k1_ge_t pub;
|
||||
secp256k1_scalar_t one;
|
||||
secp256k1_scalar_t msg, key;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t sigr, sigs;
|
||||
int recid;
|
||||
int getrec;
|
||||
random_scalar_order_test(&msg);
|
||||
|
@ -1507,14 +1508,14 @@ void test_ecdsa_sign_verify(void) {
|
|||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
|
||||
secp256k1_ge_set_gej(&pub, &pubj);
|
||||
getrec = secp256k1_rand32()&1;
|
||||
random_sign(&sig, &key, &msg, getrec?&recid:NULL);
|
||||
random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL);
|
||||
if (getrec) {
|
||||
CHECK(recid >= 0 && recid < 4);
|
||||
}
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_scalar_add(&msg, &msg, &one);
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg));
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||
}
|
||||
|
||||
void run_ecdsa_sign_verify(void) {
|
||||
|
@ -1570,9 +1571,9 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char
|
|||
return nonce_function_rfc6979(nonce32, msg32, key32, counter - 5, data);
|
||||
}
|
||||
|
||||
int is_empty_compact_signature(const unsigned char *sig64) {
|
||||
static const unsigned char res[64] = {0};
|
||||
return memcmp(sig64, res, 64) == 0;
|
||||
int is_empty_signature(const secp256k1_ecdsa_signature_t *sig) {
|
||||
static const unsigned char res[sizeof(secp256k1_ecdsa_signature_t)] = {0};
|
||||
return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature_t)) == 0;
|
||||
}
|
||||
|
||||
void test_ecdsa_end_to_end(void) {
|
||||
|
@ -1580,21 +1581,15 @@ void test_ecdsa_end_to_end(void) {
|
|||
unsigned char privkey[32];
|
||||
unsigned char message[32];
|
||||
unsigned char privkey2[32];
|
||||
unsigned char csignature[64];
|
||||
unsigned char signature[72];
|
||||
unsigned char signature2[72];
|
||||
unsigned char signature3[72];
|
||||
unsigned char signature4[72];
|
||||
unsigned char pubkey[65];
|
||||
unsigned char recpubkey[65];
|
||||
secp256k1_ecdsa_signature_t signature[5];
|
||||
unsigned char sig[74];
|
||||
int siglen = 74;
|
||||
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 +1603,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 +1620,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,59 +1637,70 @@ 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. */
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, signature, &signaturelen, privkey, NULL, NULL) == 1);
|
||||
CHECK(signaturelen > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, signature2, &signaturelen2, privkey, NULL, extra) == 1);
|
||||
CHECK(signaturelen2 > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[0], privkey, NULL, NULL) == 1);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[4], privkey, NULL, NULL) == 1);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[1], privkey, NULL, extra) == 1);
|
||||
extra[31] = 1;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, signature3, &signaturelen3, privkey, NULL, extra) == 1);
|
||||
CHECK(signaturelen3 > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[2], privkey, NULL, extra) == 1);
|
||||
extra[31] = 0;
|
||||
extra[0] = 1;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, signature4, &signaturelen4, privkey, NULL, extra) == 1);
|
||||
CHECK(signaturelen4 > 0);
|
||||
CHECK((signaturelen != signaturelen2) || (memcmp(signature, signature2, signaturelen) != 0));
|
||||
CHECK((signaturelen != signaturelen3) || (memcmp(signature, signature3, signaturelen) != 0));
|
||||
CHECK((signaturelen3 != signaturelen2) || (memcmp(signature3, signature2, signaturelen3) != 0));
|
||||
CHECK((signaturelen4 != signaturelen3) || (memcmp(signature4, signature3, signaturelen4) != 0));
|
||||
CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0));
|
||||
CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[3], privkey, NULL, extra) == 1);
|
||||
CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0);
|
||||
CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0);
|
||||
CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0);
|
||||
CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0);
|
||||
CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0);
|
||||
CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0);
|
||||
CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 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);
|
||||
/* 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[0], &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[1], &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[2], &pubkey) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[3], &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);
|
||||
/* 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);
|
||||
/* Serialize/parse DER and verify again */
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1);
|
||||
memset(&signature[0], 0, sizeof(signature[0]));
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[0], &pubkey) == 1);
|
||||
/* Serialize/destroy/parse DER and verify again. */
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1);
|
||||
sig[secp256k1_rand32() % siglen] += 1 + (secp256k1_rand32() % 255);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 ||
|
||||
secp256k1_ecdsa_verify(ctx, message, &signature[0], &pubkey) == 0);
|
||||
|
||||
/* Serialize/parse compact (without recovery id) and verify again. */
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, &recid, &signature[4]) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, NULL, &signature[4]) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 1);
|
||||
memset(&signature[4], 0, sizeof(signature[4]));
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, -1) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 1);
|
||||
/* Parse compact (with recovery id) and recover. */
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, recid) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, message, &signature[4], &recpubkey) == 1);
|
||||
CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
|
||||
/* Serialize/destroy/parse signature and verify again. */
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, &recid, &signature[4]) == 1);
|
||||
sig[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, recid) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 0);
|
||||
/* Recover again */
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, message, &signature[4], &recpubkey) == 0 ||
|
||||
memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
|
||||
}
|
||||
|
||||
void test_random_pubkeys(void) {
|
||||
|
@ -1816,9 +1802,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 +1815,18 @@ 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;
|
||||
secp256k1_ecdsa_signature_t sig;
|
||||
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_signature_parse_compact(ctx, &sig, sig64, 0));
|
||||
CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey));
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 1));
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey));
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 2));
|
||||
CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey));
|
||||
CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 3));
|
||||
CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey));
|
||||
|
||||
for (recid = 0; recid < 4; recid++) {
|
||||
int i;
|
||||
|
@ -1882,34 +1871,41 @@ 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_signature_parse_compact(ctx, &sig, sigb64, recid) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &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_signature_parse_compact(ctx, &sig, sigb64, recid2) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey2b) == 1);
|
||||
/* Verifying with (order + r,4) should always fail. */
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), pubkey2b, pubkey2blen) != 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 0);
|
||||
}
|
||||
/* 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_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0);
|
||||
/* 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_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1);
|
||||
sigbderalt3[4] = 1;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0);
|
||||
sigbderalt4[7] = 1;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), pubkeyb, pubkeyblen) == -2);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0);
|
||||
/* Damage signature. */
|
||||
sigbder[7]++;
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &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_signature_parse_der(ctx, &sig, sigbder, 6) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0);
|
||||
for(i = 0; i < 8; i++) {
|
||||
int c;
|
||||
unsigned char orig = sigbder[i];
|
||||
|
@ -1919,8 +1915,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_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 0);
|
||||
}
|
||||
sigbder[i] = orig;
|
||||
}
|
||||
|
@ -1931,15 +1926,15 @@ void test_ecdsa_edge_cases(void) {
|
|||
secp256k1_gej_t keyj;
|
||||
secp256k1_ge_t key;
|
||||
secp256k1_scalar_t msg;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_set_int(&sig.s, 1);
|
||||
secp256k1_scalar_negate(&sig.s, &sig.s);
|
||||
secp256k1_scalar_inverse(&sig.s, &sig.s);
|
||||
secp256k1_scalar_set_int(&sig.r, 1);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sig.r);
|
||||
secp256k1_scalar_t sr, ss;
|
||||
secp256k1_scalar_set_int(&ss, 1);
|
||||
secp256k1_scalar_negate(&ss, &ss);
|
||||
secp256k1_scalar_inverse(&ss, &ss);
|
||||
secp256k1_scalar_set_int(&sr, 1);
|
||||
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr);
|
||||
secp256k1_ge_set_gej(&key, &keyj);
|
||||
msg = sig.s;
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &key, &msg) == 0);
|
||||
msg = ss;
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0);
|
||||
}
|
||||
|
||||
/* Test r/s equal to zero */
|
||||
|
@ -1956,24 +1951,31 @@ 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_signature_parse_compact(ctx, &sig, sigc64, 0) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyc) == 1);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &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_signature_parse_compact(ctx, &sig, sigc64, 0) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &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_signature_parse_compact(ctx, &sig, sigc64, 0) == 1);
|
||||
CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1);
|
||||
CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyc) == 0);
|
||||
}
|
||||
|
||||
/*Signature where s would be zero.*/
|
||||
{
|
||||
unsigned char signature[72];
|
||||
int siglen;
|
||||
const unsigned char nonce[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -1998,21 +2000,15 @@ void test_ecdsa_edge_cases(void) {
|
|||
0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62,
|
||||
0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9,
|
||||
};
|
||||
unsigned char sig[72];
|
||||
int siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 0);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 0);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce) == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce2) == 0);
|
||||
msg[31] = 0xaa;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce) == 1);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce2) == 1);
|
||||
siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 1);
|
||||
CHECK(siglen > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 1);
|
||||
CHECK(siglen > 0);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1);
|
||||
siglen = 10;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) != 1);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0);
|
||||
}
|
||||
|
||||
/* Nonce function corner cases. */
|
||||
|
@ -2021,65 +2017,43 @@ void test_ecdsa_edge_cases(void) {
|
|||
int i;
|
||||
unsigned char key[32];
|
||||
unsigned char msg[32];
|
||||
unsigned char sig[72];
|
||||
unsigned char sig2[72];
|
||||
secp256k1_ecdsa_sig_t s[512];
|
||||
int siglen = 72;
|
||||
int siglen2 = 72;
|
||||
int recid2;
|
||||
secp256k1_ecdsa_signature_t sig2;
|
||||
secp256k1_scalar_t sr[512], ss;
|
||||
const unsigned char *extra;
|
||||
extra = t == 0 ? NULL : zero;
|
||||
memset(msg, 0, 32);
|
||||
msg[31] = 1;
|
||||
/* High key results in signature failure. */
|
||||
memset(key, 0xFF, 32);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 0);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, NULL, extra) == 0);
|
||||
CHECK(is_empty_signature(&sig));
|
||||
/* Zero key results in signature failure. */
|
||||
memset(key, 0, 32);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 0);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, NULL, extra) == 0);
|
||||
CHECK(is_empty_signature(&sig));
|
||||
/* Nonce function failure results in signature failure. */
|
||||
key[31] = 1;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, nonce_function_test_fail, extra) == 0);
|
||||
CHECK(siglen == 0);
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, nonce_function_test_fail, extra, &recid) == 0);
|
||||
CHECK(is_empty_compact_signature(sig));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, nonce_function_test_fail, extra) == 0);
|
||||
CHECK(is_empty_signature(&sig));
|
||||
/* The retry loop successfully makes its way to the first good value. */
|
||||
siglen = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, nonce_function_test_retry, extra) == 1);
|
||||
CHECK(siglen > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, nonce_function_rfc6979, extra) == 1);
|
||||
CHECK(siglen > 0);
|
||||
CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, nonce_function_test_retry, extra, &recid) == 1);
|
||||
CHECK(!is_empty_compact_signature(sig));
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig2, key, nonce_function_rfc6979, extra, &recid2) == 1);
|
||||
CHECK(!is_empty_compact_signature(sig2));
|
||||
CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, nonce_function_test_retry, extra) == 1);
|
||||
CHECK(!is_empty_signature(&sig));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, nonce_function_rfc6979, extra) == 1);
|
||||
CHECK(!is_empty_signature(&sig2));
|
||||
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0);
|
||||
/* The default nonce function is determinstic. */
|
||||
siglen = 72;
|
||||
siglen2 = 72;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 1);
|
||||
CHECK(siglen > 0);
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1);
|
||||
CHECK(siglen2 > 0);
|
||||
CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0));
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, NULL, extra, &recid) == 1);
|
||||
CHECK(!is_empty_compact_signature(sig));
|
||||
CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig2, key, NULL, extra, &recid2) == 1);
|
||||
CHECK(!is_empty_compact_signature(sig));
|
||||
CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1);
|
||||
CHECK(!is_empty_signature(&sig2));
|
||||
CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0);
|
||||
/* The default nonce function changes output with different messages. */
|
||||
for(i = 0; i < 256; i++) {
|
||||
int j;
|
||||
siglen2 = 72;
|
||||
msg[0] = i;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1);
|
||||
CHECK(!is_empty_compact_signature(sig));
|
||||
CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1);
|
||||
CHECK(!is_empty_signature(&sig2));
|
||||
secp256k1_ecdsa_signature_load(&sr[i], &ss, NULL, &sig2);
|
||||
for (j = 0; j < i; j++) {
|
||||
CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
|
||||
CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j]));
|
||||
}
|
||||
}
|
||||
msg[0] = 0;
|
||||
|
@ -2087,12 +2061,12 @@ void test_ecdsa_edge_cases(void) {
|
|||
/* The default nonce function changes output with different keys. */
|
||||
for(i = 256; i < 512; i++) {
|
||||
int j;
|
||||
siglen2 = 72;
|
||||
key[0] = i - 256;
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1);
|
||||
CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2));
|
||||
CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1);
|
||||
CHECK(!is_empty_signature(&sig2));
|
||||
secp256k1_ecdsa_signature_load(&sr[i], &ss, NULL, &sig2);
|
||||
for (j = 0; j < i; j++) {
|
||||
CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));
|
||||
CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j]));
|
||||
}
|
||||
}
|
||||
key[0] = 0;
|
||||
|
@ -2133,7 +2107,7 @@ EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) {
|
|||
void test_ecdsa_openssl(void) {
|
||||
secp256k1_gej_t qj;
|
||||
secp256k1_ge_t q;
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_scalar_t sigr, sigs;
|
||||
secp256k1_scalar_t one;
|
||||
secp256k1_scalar_t msg2;
|
||||
secp256k1_scalar_t key, msg;
|
||||
|
@ -2150,14 +2124,14 @@ void test_ecdsa_openssl(void) {
|
|||
ec_key = get_openssl_key(&key);
|
||||
CHECK(ec_key);
|
||||
CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
|
||||
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &q, &msg));
|
||||
CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize));
|
||||
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg));
|
||||
secp256k1_scalar_set_int(&one, 1);
|
||||
secp256k1_scalar_add(&msg2, &msg, &one);
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &q, &msg2));
|
||||
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2));
|
||||
|
||||
random_sign(&sig, &key, &msg, NULL);
|
||||
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig));
|
||||
random_sign(&sigr, &sigs, &key, &msg, NULL);
|
||||
CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs));
|
||||
CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1);
|
||||
|
||||
EC_KEY_free(ec_key);
|
||||
|
|
Loading…
Reference in New Issue