cryptoconditions secp256k1 tests canonical signature

This commit is contained in:
Scott Sadler
2018-03-17 23:09:14 -03:00
parent aaff5dd10c
commit 49cd4daab2
4 changed files with 41 additions and 1 deletions

View File

@@ -95,6 +95,18 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
/** Check that signature is in canonical form
* Returns: 1: In canonical form
* 0: Non canonical
* -1: invalid signature
* In: sig: the signature being verified (cannot be NULL)
* siglen: the length of the signature
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_check_canonical_sig(
const unsigned char *sig,
int siglen
) SECP256K1_ARG_NONNULL(1);
/** A pointer to a function to deterministically generate a nonce.
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
* In: msg32: the 32-byte message hash being verified (will not be NULL)

View File

@@ -85,6 +85,14 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *
return ret;
}
int secp256k1_ecdsa_check_canonical_sig(const unsigned char *sig, int siglen) {
secp256k1_ecdsa_sig_t s;
if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) return -1;
return !secp256k1_scalar_is_high(&s.s);
}
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) {
secp256k1_rfc6979_hmac_sha256_t rng;
unsigned int i;

View File

@@ -77,7 +77,12 @@ int secp256k1Verify(CC *cond, CCVisitor visitor) {
if (cond->type->typeId != cc_secp256k1Type.typeId) return 1;
// TODO: test failure mode: empty sig / null pointer
initVerify();
int rc = secp256k1_ecdsa_verify(ec_ctx_verify, visitor.msg, cond->signature, SECP256K1_SIG_SIZE,
// Test for non canonical S
int rc = secp256k1_ecdsa_check_canonical_sig(cond->signature, SECP256K1_SIG_SIZE);
if (rc == 1)
// Test for correct sig
rc = secp256k1_ecdsa_verify(ec_ctx_verify, visitor.msg, cond->signature, SECP256K1_SIG_SIZE,
cond->publicKey, SECP256K1_PK_SIZE);
return rc == 1;
}

View File

@@ -61,3 +61,18 @@ def test_decode_invalid_condition():
def test_validate_empty_sigs():
#// TODO: test failure mode: empty sig / null pointer
pass
def test_non_canonical_secp256k1():
cond = {
"type": "secp256k1-sha-256",
"publicKey": "AtXZaTBVNawpp3B5wR1PDdQGYc-W4E6XSl6NfjdO4iWq",
# Signature is correct, but non canonical; validation should fail
"signature": "nC1v8580C7r2XohL3_rnQ2p7dWiDnFuhF_poGCRfudrDITgwKywgjm5CTdnHAnkK4QskG4nI0KBrActwgzSrbg"
}
res = jsonRPC('verifyFulfillment', {
'fulfillment': jsonRPC('encodeFulfillment', cond)['fulfillment'],
'condition': jsonRPC('encodeCondition', cond)['bin'],
'message': ''
})
assert res['valid'] == False