tests_exhaustive_impl.h (10655B)
1 /*********************************************************************** 2 * Copyright (c) 2020 Pieter Wuille * 3 * Distributed under the MIT software license, see the accompanying * 4 * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 ***********************************************************************/ 6 7 #ifndef SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H 8 #define SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H 9 10 #include "../../../include/secp256k1_schnorrsig.h" 11 #include "main_impl.h" 12 13 static const unsigned char invalid_pubkey_bytes[][32] = { 14 /* 0 */ 15 { 16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 18 }, 19 /* 2 */ 20 { 21 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 23 }, 24 /* order */ 25 { 26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 24) & 0xFF, 29 ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 16) & 0xFF, 30 ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 8) & 0xFF, 31 (EXHAUSTIVE_TEST_ORDER + 0UL) & 0xFF 32 }, 33 /* order + 1 */ 34 { 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37 ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 24) & 0xFF, 38 ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 16) & 0xFF, 39 ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 8) & 0xFF, 40 (EXHAUSTIVE_TEST_ORDER + 1UL) & 0xFF 41 }, 42 /* field size */ 43 { 44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 45 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F 46 }, 47 /* field size + 1 (note that 1 is legal) */ 48 { 49 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 50 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 51 }, 52 /* 2^256 - 1 */ 53 { 54 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 55 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 56 } 57 }; 58 59 #define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) 60 61 static int haskellsecp256k1_v0_1_0_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg, 62 size_t msglen, 63 const unsigned char *key32, const unsigned char *xonly_pk32, 64 const unsigned char *algo, size_t algolen, 65 void* data) { 66 haskellsecp256k1_v0_1_0_scalar s; 67 int *idata = data; 68 (void)msg; 69 (void)msglen; 70 (void)key32; 71 (void)xonly_pk32; 72 (void)algo; 73 (void)algolen; 74 haskellsecp256k1_v0_1_0_scalar_set_int(&s, *idata); 75 haskellsecp256k1_v0_1_0_scalar_get_b32(nonce32, &s); 76 return 1; 77 } 78 79 static void test_exhaustive_schnorrsig_verify(const haskellsecp256k1_v0_1_0_context *ctx, const haskellsecp256k1_v0_1_0_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { 80 int d; 81 uint64_t iter = 0; 82 /* Iterate over the possible public keys to verify against (through their corresponding DL d). */ 83 for (d = 1; d <= EXHAUSTIVE_TEST_ORDER / 2; ++d) { 84 int actual_d; 85 unsigned k; 86 unsigned char pk32[32]; 87 memcpy(pk32, xonly_pubkey_bytes[d - 1], 32); 88 actual_d = parities[d - 1] ? EXHAUSTIVE_TEST_ORDER - d : d; 89 /* Iterate over the possible valid first 32 bytes in the signature, through their corresponding DL k. 90 Values above EXHAUSTIVE_TEST_ORDER/2 refer to the entries in invalid_pubkey_bytes. */ 91 for (k = 1; k <= EXHAUSTIVE_TEST_ORDER / 2 + NUM_INVALID_KEYS; ++k) { 92 unsigned char sig64[64]; 93 int actual_k = -1; 94 int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; 95 int e_count_done = 0; 96 if (skip_section(&iter)) continue; 97 if (k <= EXHAUSTIVE_TEST_ORDER / 2) { 98 memcpy(sig64, xonly_pubkey_bytes[k - 1], 32); 99 actual_k = parities[k - 1] ? EXHAUSTIVE_TEST_ORDER - k : k; 100 } else { 101 memcpy(sig64, invalid_pubkey_bytes[k - 1 - EXHAUSTIVE_TEST_ORDER / 2], 32); 102 } 103 /* Randomly generate messages until all challenges have been hit. */ 104 while (e_count_done < EXHAUSTIVE_TEST_ORDER) { 105 haskellsecp256k1_v0_1_0_scalar e; 106 unsigned char msg32[32]; 107 haskellsecp256k1_v0_1_0_testrand256(msg32); 108 haskellsecp256k1_v0_1_0_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); 109 /* Only do work if we hit a challenge we haven't tried before. */ 110 if (!e_done[e]) { 111 /* Iterate over the possible valid last 32 bytes in the signature. 112 0..order=that s value; order+1=random bytes */ 113 int count_valid = 0; 114 unsigned int s; 115 for (s = 0; s <= EXHAUSTIVE_TEST_ORDER + 1; ++s) { 116 int expect_valid, valid; 117 if (s <= EXHAUSTIVE_TEST_ORDER) { 118 memset(sig64 + 32, 0, 32); 119 haskellsecp256k1_v0_1_0_write_be32(sig64 + 60, s); 120 expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && 121 (s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); 122 } else { 123 haskellsecp256k1_v0_1_0_testrand256(sig64 + 32); 124 expect_valid = 0; 125 } 126 valid = haskellsecp256k1_v0_1_0_schnorrsig_verify(ctx, sig64, msg32, sizeof(msg32), &pubkeys[d - 1]); 127 CHECK(valid == expect_valid); 128 count_valid += valid; 129 } 130 /* Exactly one s value must verify, unless R is illegal. */ 131 CHECK(count_valid == (actual_k != -1)); 132 /* Don't retry other messages that result in the same challenge. */ 133 e_done[e] = 1; 134 ++e_count_done; 135 } 136 } 137 } 138 } 139 } 140 141 static void test_exhaustive_schnorrsig_sign(const haskellsecp256k1_v0_1_0_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const haskellsecp256k1_v0_1_0_keypair* keypairs, const int* parities) { 142 int d, k; 143 uint64_t iter = 0; 144 haskellsecp256k1_v0_1_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; 145 146 /* Loop over keys. */ 147 for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { 148 int actual_d = d; 149 if (parities[d - 1]) actual_d = EXHAUSTIVE_TEST_ORDER - d; 150 /* Loop over nonces. */ 151 for (k = 1; k < EXHAUSTIVE_TEST_ORDER; ++k) { 152 int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; 153 int e_count_done = 0; 154 unsigned char msg32[32]; 155 unsigned char sig64[64]; 156 int actual_k = k; 157 if (skip_section(&iter)) continue; 158 extraparams.noncefp = haskellsecp256k1_v0_1_0_hardened_nonce_function_smallint; 159 extraparams.ndata = &k; 160 if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; 161 /* Generate random messages until all challenges have been tried. */ 162 while (e_count_done < EXHAUSTIVE_TEST_ORDER) { 163 haskellsecp256k1_v0_1_0_scalar e; 164 haskellsecp256k1_v0_1_0_testrand256(msg32); 165 haskellsecp256k1_v0_1_0_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); 166 /* Only do work if we hit a challenge we haven't tried before. */ 167 if (!e_done[e]) { 168 haskellsecp256k1_v0_1_0_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; 169 unsigned char expected_s_bytes[32]; 170 haskellsecp256k1_v0_1_0_scalar_get_b32(expected_s_bytes, &expected_s); 171 /* Invoke the real function to construct a signature. */ 172 CHECK(haskellsecp256k1_v0_1_0_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams)); 173 /* The first 32 bytes must match the xonly pubkey for the specified k. */ 174 CHECK(haskellsecp256k1_v0_1_0_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); 175 /* The last 32 bytes must match the expected s value. */ 176 CHECK(haskellsecp256k1_v0_1_0_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); 177 /* Don't retry other messages that result in the same challenge. */ 178 e_done[e] = 1; 179 ++e_count_done; 180 } 181 } 182 } 183 } 184 } 185 186 static void test_exhaustive_schnorrsig(const haskellsecp256k1_v0_1_0_context *ctx) { 187 haskellsecp256k1_v0_1_0_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; 188 haskellsecp256k1_v0_1_0_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; 189 int parity[EXHAUSTIVE_TEST_ORDER - 1]; 190 unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; 191 unsigned i; 192 193 /* Verify that all invalid_pubkey_bytes are actually invalid. */ 194 for (i = 0; i < NUM_INVALID_KEYS; ++i) { 195 haskellsecp256k1_v0_1_0_xonly_pubkey pk; 196 CHECK(!haskellsecp256k1_v0_1_0_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); 197 } 198 199 /* Construct keypairs and xonly-pubkeys for the entire group. */ 200 for (i = 1; i < EXHAUSTIVE_TEST_ORDER; ++i) { 201 haskellsecp256k1_v0_1_0_scalar scalar_i; 202 unsigned char buf[32]; 203 haskellsecp256k1_v0_1_0_scalar_set_int(&scalar_i, i); 204 haskellsecp256k1_v0_1_0_scalar_get_b32(buf, &scalar_i); 205 CHECK(haskellsecp256k1_v0_1_0_keypair_create(ctx, &keypair[i - 1], buf)); 206 CHECK(haskellsecp256k1_v0_1_0_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); 207 CHECK(haskellsecp256k1_v0_1_0_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); 208 } 209 210 test_exhaustive_schnorrsig_sign(ctx, xonly_pubkey_bytes, keypair, parity); 211 test_exhaustive_schnorrsig_verify(ctx, xonly_pubkey, xonly_pubkey_bytes, parity); 212 } 213 214 #endif