csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1 (docs.ppad.tech/csecp256k1).
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

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