github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h (about)

     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 secp256k1_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      secp256k1_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      secp256k1_scalar_set_int(&s, *idata);
    75      secp256k1_scalar_get_b32(nonce32, &s);
    76      return 1;
    77  }
    78  
    79  static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, const secp256k1_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                  secp256k1_scalar e;
   106                  unsigned char msg32[32];
   107                  testrand256(msg32);
   108                  secp256k1_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                              secp256k1_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                              testrand256(sig64 + 32);
   124                              expect_valid = 0;
   125                          }
   126                          valid = secp256k1_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 secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) {
   142      int d, k;
   143      uint64_t iter = 0;
   144      secp256k1_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 = secp256k1_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                  secp256k1_scalar e;
   164                  testrand256(msg32);
   165                  secp256k1_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                      secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER;
   169                      unsigned char expected_s_bytes[32];
   170                      secp256k1_scalar_get_b32(expected_s_bytes, &expected_s);
   171                      /* Invoke the real function to construct a signature. */
   172                      CHECK(secp256k1_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(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0);
   175                      /* The last 32 bytes must match the expected s value. */
   176                      CHECK(secp256k1_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 secp256k1_context *ctx) {
   187      secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1];
   188      secp256k1_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          secp256k1_xonly_pubkey pk;
   196          CHECK(!secp256k1_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          secp256k1_scalar scalar_i;
   202          unsigned char buf[32];
   203          secp256k1_scalar_set_int(&scalar_i, i);
   204          secp256k1_scalar_get_b32(buf, &scalar_i);
   205          CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf));
   206          CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1]));
   207          CHECK(secp256k1_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