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 (6364B)


      1 /***********************************************************************
      2  * Copyright (c) 2015 Andrew Poelstra                                  *
      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_ECDH_TESTS_H
      8 #define SECP256K1_MODULE_ECDH_TESTS_H
      9 
     10 static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
     11     (void)output;
     12     (void)x;
     13     (void)y;
     14     (void)data;
     15     return 0;
     16 }
     17 
     18 static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
     19     (void)data;
     20     /* Save x and y as uncompressed public key */
     21     output[0] = 0x04;
     22     memcpy(output + 1, x, 32);
     23     memcpy(output + 33, y, 32);
     24     return 1;
     25 }
     26 
     27 static void test_ecdh_api(void) {
     28     haskellsecp256k1_v0_1_0_pubkey point;
     29     unsigned char res[32];
     30     unsigned char s_one[32] = { 0 };
     31     s_one[31] = 1;
     32 
     33     CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point, s_one) == 1);
     34 
     35     /* Check all NULLs are detected */
     36     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
     37     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdh(CTX, NULL, &point, s_one, NULL, NULL));
     38     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdh(CTX, res, NULL, s_one, NULL, NULL));
     39     CHECK_ILLEGAL(CTX, haskellsecp256k1_v0_1_0_ecdh(CTX, res, &point, NULL, NULL, NULL));
     40     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
     41 }
     42 
     43 static void test_ecdh_generator_basepoint(void) {
     44     unsigned char s_one[32] = { 0 };
     45     haskellsecp256k1_v0_1_0_pubkey point[2];
     46     int i;
     47 
     48     s_one[31] = 1;
     49     /* Check against pubkey creation when the basepoint is the generator */
     50     for (i = 0; i < 2 * COUNT; ++i) {
     51         haskellsecp256k1_v0_1_0_sha256 sha;
     52         unsigned char s_b32[32];
     53         unsigned char output_ecdh[65];
     54         unsigned char output_ser[32];
     55         unsigned char point_ser[65];
     56         size_t point_ser_len = sizeof(point_ser);
     57         haskellsecp256k1_v0_1_0_scalar s;
     58 
     59         random_scalar_order(&s);
     60         haskellsecp256k1_v0_1_0_scalar_get_b32(s_b32, &s);
     61 
     62         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point[0], s_one) == 1);
     63         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point[1], s_b32) == 1);
     64 
     65         /* compute using ECDH function with custom hash function */
     66         CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
     67         /* compute "explicitly" */
     68         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
     69         /* compare */
     70         CHECK(haskellsecp256k1_v0_1_0_memcmp_var(output_ecdh, point_ser, 65) == 0);
     71 
     72         /* compute using ECDH function with default hash function */
     73         CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
     74         /* compute "explicitly" */
     75         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
     76         haskellsecp256k1_v0_1_0_sha256_initialize(&sha);
     77         haskellsecp256k1_v0_1_0_sha256_write(&sha, point_ser, point_ser_len);
     78         haskellsecp256k1_v0_1_0_sha256_finalize(&sha, output_ser);
     79         /* compare */
     80         CHECK(haskellsecp256k1_v0_1_0_memcmp_var(output_ecdh, output_ser, 32) == 0);
     81     }
     82 }
     83 
     84 static void test_bad_scalar(void) {
     85     unsigned char s_zero[32] = { 0 };
     86     unsigned char s_overflow[32] = {
     87         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     88         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
     89         0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
     90         0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
     91     };
     92     unsigned char s_rand[32] = { 0 };
     93     unsigned char output[32];
     94     haskellsecp256k1_v0_1_0_scalar rand;
     95     haskellsecp256k1_v0_1_0_pubkey point;
     96 
     97     /* Create random point */
     98     random_scalar_order(&rand);
     99     haskellsecp256k1_v0_1_0_scalar_get_b32(s_rand, &rand);
    100     CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point, s_rand) == 1);
    101 
    102     /* Try to multiply it by bad values */
    103     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0);
    104     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0);
    105     /* ...and a good one */
    106     s_overflow[31] -= 1;
    107     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1);
    108 
    109     /* Hash function failure results in ecdh failure */
    110     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
    111 }
    112 
    113 /** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */
    114 static void test_result_basepoint(void) {
    115     haskellsecp256k1_v0_1_0_pubkey point;
    116     haskellsecp256k1_v0_1_0_scalar rand;
    117     unsigned char s[32];
    118     unsigned char s_inv[32];
    119     unsigned char out[32];
    120     unsigned char out_inv[32];
    121     unsigned char out_base[32];
    122     int i;
    123 
    124     unsigned char s_one[32] = { 0 };
    125     s_one[31] = 1;
    126     CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point, s_one) == 1);
    127     CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1);
    128 
    129     for (i = 0; i < 2 * COUNT; i++) {
    130         random_scalar_order(&rand);
    131         haskellsecp256k1_v0_1_0_scalar_get_b32(s, &rand);
    132         haskellsecp256k1_v0_1_0_scalar_inverse(&rand, &rand);
    133         haskellsecp256k1_v0_1_0_scalar_get_b32(s_inv, &rand);
    134 
    135         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point, s) == 1);
    136         CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1);
    137         CHECK(haskellsecp256k1_v0_1_0_memcmp_var(out, out_base, 32) == 0);
    138 
    139         CHECK(haskellsecp256k1_v0_1_0_ec_pubkey_create(CTX, &point, s_inv) == 1);
    140         CHECK(haskellsecp256k1_v0_1_0_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1);
    141         CHECK(haskellsecp256k1_v0_1_0_memcmp_var(out_inv, out_base, 32) == 0);
    142     }
    143 }
    144 
    145 static void run_ecdh_tests(void) {
    146     test_ecdh_api();
    147     test_ecdh_generator_basepoint();
    148     test_bad_scalar();
    149     test_result_basepoint();
    150 }
    151 
    152 #endif /* SECP256K1_MODULE_ECDH_TESTS_H */