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_impl.h (19708B)


      1 /***********************************************************************
      2  * Copyright (c) 2013-2015 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_RECOVERY_TESTS_H
      8 #define SECP256K1_MODULE_RECOVERY_TESTS_H
      9 
     10 static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
     11     (void) msg32;
     12     (void) key32;
     13     (void) algo16;
     14     (void) data;
     15 
     16     /* On the first run, return 0 to force a second run */
     17     if (counter == 0) {
     18         memset(nonce32, 0, 32);
     19         return 1;
     20     }
     21     /* On the second run, return an overflow to force a third run */
     22     if (counter == 1) {
     23         memset(nonce32, 0xff, 32);
     24         return 1;
     25     }
     26     /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */
     27     memset(nonce32, 1, 32);
     28     return haskellsecp256k1_v0_1_0_testrand_bits(1);
     29 }
     30 
     31 static void test_ecdsa_recovery_api(void) {
     32     /* Setup contexts that just count errors */
     33     haskellsecp256k1_v0_1_0_pubkey pubkey;
     34     haskellsecp256k1_v0_1_0_pubkey recpubkey;
     35     haskellsecp256k1_v0_1_0_ecdsa_signature normal_sig;
     36     haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature recsig;
     37     unsigned char privkey[32] = { 1 };
     38     unsigned char message[32] = { 2 };
     39     int recid = 0;
     40     unsigned char sig[74];
     41     unsigned char zero_privkey[32] = { 0 };
     42     unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     43                                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     44                                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     45                                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     46 
     47     /* Construct and verify corresponding public key. */
     48     CHECK(haskellsecp256k1_v0_1_0_ec_seckey_verify(CTX, privkey) == 1);
     49     CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &pubkey, privkey) == 1);
     50 
     51     /* Check bad contexts and NULLs for signing */
     52     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1);
     53     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, NULL, message, privkey, NULL, NULL));
     54     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, NULL, privkey, NULL, NULL));
     55     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, NULL, NULL, NULL));
     56     CHECK_ILLEGAL(STATIC_CTX, haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(STATIC_CTX, &recsig, message, privkey, NULL, NULL));
     57     /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
     58     haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, recovery_test_nonce_function, NULL);
     59     /* These will all fail, but not in ARG_CHECK way */
     60     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, zero_privkey, NULL, NULL) == 0);
     61     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, over_privkey, NULL, NULL) == 0);
     62     /* This one will succeed. */
     63     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1);
     64 
     65     /* Check signing with a goofy nonce function */
     66 
     67     /* Check bad contexts and NULLs for recovery */
     68     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &recpubkey, &recsig, message) == 1);
     69     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, NULL, &recsig, message));
     70     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &recpubkey, NULL, message));
     71     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &recpubkey, &recsig, NULL));
     72 
     73     /* Check NULLs for conversion */
     74     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign(CTX, &normal_sig, message, privkey, NULL, NULL) == 1);
     75     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, NULL, &recsig));
     76     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, &normal_sig, NULL));
     77     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, &normal_sig, &recsig) == 1);
     78 
     79     /* Check NULLs for de/serialization */
     80     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1);
     81     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, NULL, &recid, &recsig));
     82     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, NULL, &recsig));
     83     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, NULL));
     84     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &recsig) == 1);
     85 
     86     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, NULL, sig, recid));
     87     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, NULL, recid));
     88     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, -1));
     89     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, 5));
     90     /* overflow in signature will not result in calling illegal_callback */
     91     memcpy(sig, over_privkey, 32);
     92     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, recid) == 0);
     93 }
     94 
     95 static void test_ecdsa_recovery_end_to_end(void) {
     96     unsigned char extra[32] = {0x00};
     97     unsigned char privkey[32];
     98     unsigned char message[32];
     99     haskellsecp256k1_v0_1_0_ecdsa_signature signature[5];
    100     haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature rsignature[5];
    101     unsigned char sig[74];
    102     haskellsecp256k1_v0_1_0_pubkey pubkey;
    103     haskellsecp256k1_v0_1_0_pubkey recpubkey;
    104     int recid = 0;
    105 
    106     /* Generate a random key and message. */
    107     {
    108         haskellsecp256k1_v0_1_0_scalar msg, key;
    109         random_scalar_order_test(&msg);
    110         random_scalar_order_test(&key);
    111         haskellsecp256k1_v0_1_0_scalar_get_b32(privkey, &key);
    112         haskellsecp256k1_v0_1_0_scalar_get_b32(message, &msg);
    113     }
    114 
    115     /* Construct and verify corresponding public key. */
    116     CHECK(haskellsecp256k1_v0_1_0_ec_seckey_verify(CTX, privkey) == 1);
    117     CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &pubkey, privkey) == 1);
    118 
    119     /* Serialize/parse compact and verify/recover. */
    120     extra[0] = 0;
    121     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &rsignature[0], message, privkey, NULL, NULL) == 1);
    122     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1);
    123     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &rsignature[4], message, privkey, NULL, NULL) == 1);
    124     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &rsignature[1], message, privkey, NULL, extra) == 1);
    125     extra[31] = 1;
    126     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &rsignature[2], message, privkey, NULL, extra) == 1);
    127     extra[31] = 0;
    128     extra[0] = 1;
    129     CHECK(haskellsecp256k1_v0_1_0_ecdsa_sign_recoverable(CTX, &rsignature[3], message, privkey, NULL, extra) == 1);
    130     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1);
    131     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1);
    132     CHECK(haskellsecp256k1_v0_1_0_memcmp_var(&signature[4], &signature[0], 64) == 0);
    133     CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1);
    134     memset(&rsignature[4], 0, sizeof(rsignature[4]));
    135     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1);
    136     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1);
    137     CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1);
    138     /* Parse compact (with recovery id) and recover. */
    139     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1);
    140     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 1);
    141     CHECK(haskellsecp256k1_v0_1_0_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0);
    142     /* Serialize/destroy/parse signature and verify again. */
    143     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1);
    144     sig[haskellsecp256k1_v0_1_0_testrand_bits(6)] += 1 + haskellsecp256k1_v0_1_0_testrand_int(255);
    145     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1);
    146     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1);
    147     CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 0);
    148     /* Recover again */
    149     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 0 ||
    150           haskellsecp256k1_v0_1_0_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0);
    151 }
    152 
    153 /* Tests several edge cases. */
    154 static void test_ecdsa_recovery_edge_cases(void) {
    155     const unsigned char msg32[32] = {
    156         'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
    157         'a', ' ', 'v', 'e', 'r', 'y', ' ', 's',
    158         'e', 'c', 'r', 'e', 't', ' ', 'm', 'e',
    159         's', 's', 'a', 'g', 'e', '.', '.', '.'
    160     };
    161     const unsigned char sig64[64] = {
    162         /* Generated by signing the above message with nonce 'This is the nonce we will use...'
    163          * and secret key 0 (which is not valid), resulting in recid 1. */
    164         0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8,
    165         0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96,
    166         0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63,
    167         0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32,
    168         0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E,
    169         0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD,
    170         0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86,
    171         0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57
    172     };
    173     haskellsecp256k1_v0_1_0_pubkey pubkey;
    174     /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */
    175     const unsigned char sigb64[64] = {
    176         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    177         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    178         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    179         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    180         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    181         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    182         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    183         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    184     };
    185     haskellsecp256k1_v0_1_0_pubkey pubkeyb;
    186     haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature rsig;
    187     haskellsecp256k1_v0_1_0_ecdsa_signature sig;
    188     int recid;
    189 
    190     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 0));
    191     CHECK(!haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32));
    192     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 1));
    193     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32));
    194     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 2));
    195     CHECK(!haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32));
    196     CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 3));
    197     CHECK(!haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32));
    198 
    199     for (recid = 0; recid < 4; recid++) {
    200         int i;
    201         int recid2;
    202         /* (4,4) encoded in DER. */
    203         unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04};
    204         unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01};
    205         unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00};
    206         unsigned char sigbderalt1[39] = {
    207             0x30, 0x25, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
    208             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    209             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    210             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    211             0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04,
    212         };
    213         unsigned char sigbderalt2[39] = {
    214             0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 0x00,
    215             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    216             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    217             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    218             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    219         };
    220         unsigned char sigbderalt3[40] = {
    221             0x30, 0x26, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00,
    222             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    223             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    224             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    225             0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x04,
    226         };
    227         unsigned char sigbderalt4[40] = {
    228             0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 0x00,
    229             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    230             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    231             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    232             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
    233         };
    234         /* (order + r,4) encoded in DER. */
    235         unsigned char sigbderlong[40] = {
    236             0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF,
    237             0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    238             0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC,
    239             0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E,
    240             0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04
    241         };
    242         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid) == 1);
    243         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 1);
    244         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1);
    245         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 1);
    246         for (recid2 = 0; recid2 < 4; recid2++) {
    247             haskellsecp256k1_v0_1_0_pubkey pubkey2b;
    248             CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid2) == 1);
    249             CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkey2b, &rsig, msg32) == 1);
    250             /* Verifying with (order + r,4) should always fail. */
    251             CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderlong, sizeof(sigbderlong)) == 1);
    252             CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0);
    253         }
    254         /* DER parsing tests. */
    255         /* Zero length r/s. */
    256         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0);
    257         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0);
    258         /* Leading zeros. */
    259         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0);
    260         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0);
    261         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0);
    262         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0);
    263         sigbderalt3[4] = 1;
    264         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1);
    265         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0);
    266         sigbderalt4[7] = 1;
    267         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1);
    268         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0);
    269         /* Damage signature. */
    270         sigbder[7]++;
    271         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1);
    272         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0);
    273         sigbder[7]--;
    274         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, 6) == 0);
    275         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder) - 1) == 0);
    276         for(i = 0; i < 8; i++) {
    277             int c;
    278             unsigned char orig = sigbder[i];
    279             /*Try every single-byte change.*/
    280             for (c = 0; c < 256; c++) {
    281                 if (c == orig ) {
    282                     continue;
    283                 }
    284                 sigbder[i] = c;
    285                 CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 0 || haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0);
    286             }
    287             sigbder[i] = orig;
    288         }
    289     }
    290 
    291     /* Test r/s equal to zero */
    292     {
    293         /* (1,1) encoded in DER. */
    294         unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01};
    295         unsigned char sigc64[64] = {
    296             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    297             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    298             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    299             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    300             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    301             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    302             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    303             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    304         };
    305         haskellsecp256k1_v0_1_0_pubkey pubkeyc;
    306         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1);
    307         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkeyc, &rsig, msg32) == 1);
    308         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1);
    309         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 1);
    310         sigcder[4] = 0;
    311         sigc64[31] = 0;
    312         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1);
    313         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0);
    314         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1);
    315         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0);
    316         sigcder[4] = 1;
    317         sigcder[7] = 0;
    318         sigc64[31] = 1;
    319         sigc64[63] = 0;
    320         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1);
    321         CHECK(haskellsecp256k1_v0_1_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0);
    322         CHECK(haskellsecp256k1_v0_1_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1);
    323         CHECK(haskellsecp256k1_v0_1_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0);
    324     }
    325 }
    326 
    327 static void run_recovery_tests(void) {
    328     int i;
    329     for (i = 0; i < COUNT; i++) {
    330         test_ecdsa_recovery_api();
    331     }
    332     for (i = 0; i < 64*COUNT; i++) {
    333         test_ecdsa_recovery_end_to_end();
    334     }
    335     test_ecdsa_recovery_edge_cases();
    336 }
    337 
    338 #endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */