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

main_impl.h (11498B)


      1 /***********************************************************************
      2  * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick                 *
      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_MAIN_H
      8 #define SECP256K1_MODULE_SCHNORRSIG_MAIN_H
      9 
     10 #include "../../../include/secp256k1.h"
     11 #include "../../../include/secp256k1_schnorrsig.h"
     12 #include "../../hash.h"
     13 
     14 /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
     15  * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */
     16 static void haskellsecp256k1_v0_1_0_nonce_function_bip340_sha256_tagged(haskellsecp256k1_v0_1_0_sha256 *sha) {
     17     haskellsecp256k1_v0_1_0_sha256_initialize(sha);
     18     sha->s[0] = 0x46615b35ul;
     19     sha->s[1] = 0xf4bfbff7ul;
     20     sha->s[2] = 0x9f8dc671ul;
     21     sha->s[3] = 0x83627ab3ul;
     22     sha->s[4] = 0x60217180ul;
     23     sha->s[5] = 0x57358661ul;
     24     sha->s[6] = 0x21a29e54ul;
     25     sha->s[7] = 0x68b07b4cul;
     26 
     27     sha->bytes = 64;
     28 }
     29 
     30 /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
     31  * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */
     32 static void haskellsecp256k1_v0_1_0_nonce_function_bip340_sha256_tagged_aux(haskellsecp256k1_v0_1_0_sha256 *sha) {
     33     haskellsecp256k1_v0_1_0_sha256_initialize(sha);
     34     sha->s[0] = 0x24dd3219ul;
     35     sha->s[1] = 0x4eba7e70ul;
     36     sha->s[2] = 0xca0fabb9ul;
     37     sha->s[3] = 0x0fa3166dul;
     38     sha->s[4] = 0x3afbe4b1ul;
     39     sha->s[5] = 0x4c44df97ul;
     40     sha->s[6] = 0x4aac2739ul;
     41     sha->s[7] = 0x249e850aul;
     42 
     43     sha->bytes = 64;
     44 }
     45 
     46 /* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
     47  * by using the correct tagged hash function. */
     48 static const unsigned char bip340_algo[13] = "BIP0340/nonce";
     49 
     50 static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC;
     51 
     52 static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
     53     haskellsecp256k1_v0_1_0_sha256 sha;
     54     unsigned char masked_key[32];
     55     int i;
     56 
     57     if (algo == NULL) {
     58         return 0;
     59     }
     60 
     61     if (data != NULL) {
     62         haskellsecp256k1_v0_1_0_nonce_function_bip340_sha256_tagged_aux(&sha);
     63         haskellsecp256k1_v0_1_0_sha256_write(&sha, data, 32);
     64         haskellsecp256k1_v0_1_0_sha256_finalize(&sha, masked_key);
     65         for (i = 0; i < 32; i++) {
     66             masked_key[i] ^= key32[i];
     67         }
     68     } else {
     69         /* Precomputed TaggedHash("BIP0340/aux", 0x0000...00); */
     70         static const unsigned char ZERO_MASK[32] = {
     71               84, 241, 105, 207, 201, 226, 229, 114,
     72              116, 128,  68,  31, 144, 186,  37, 196,
     73              136, 244,  97, 199,  11,  94, 165, 220,
     74              170, 247, 175, 105, 39,  10, 165,  20
     75         };
     76         for (i = 0; i < 32; i++) {
     77             masked_key[i] = key32[i] ^ ZERO_MASK[i];
     78         }
     79     }
     80 
     81     /* Tag the hash with algo which is important to avoid nonce reuse across
     82      * algorithms. If this nonce function is used in BIP-340 signing as defined
     83      * in the spec, an optimized tagging implementation is used. */
     84     if (algolen == sizeof(bip340_algo)
     85             && haskellsecp256k1_v0_1_0_memcmp_var(algo, bip340_algo, algolen) == 0) {
     86         haskellsecp256k1_v0_1_0_nonce_function_bip340_sha256_tagged(&sha);
     87     } else {
     88         haskellsecp256k1_v0_1_0_sha256_initialize_tagged(&sha, algo, algolen);
     89     }
     90 
     91     /* Hash masked-key||pk||msg using the tagged hash as per the spec */
     92     haskellsecp256k1_v0_1_0_sha256_write(&sha, masked_key, 32);
     93     haskellsecp256k1_v0_1_0_sha256_write(&sha, xonly_pk32, 32);
     94     haskellsecp256k1_v0_1_0_sha256_write(&sha, msg, msglen);
     95     haskellsecp256k1_v0_1_0_sha256_finalize(&sha, nonce32);
     96     return 1;
     97 }
     98 
     99 const haskellsecp256k1_v0_1_0_nonce_function_hardened haskellsecp256k1_v0_1_0_nonce_function_bip340 = nonce_function_bip340;
    100 
    101 /* Initializes SHA256 with fixed midstate. This midstate was computed by applying
    102  * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */
    103 static void haskellsecp256k1_v0_1_0_schnorrsig_sha256_tagged(haskellsecp256k1_v0_1_0_sha256 *sha) {
    104     haskellsecp256k1_v0_1_0_sha256_initialize(sha);
    105     sha->s[0] = 0x9cecba11ul;
    106     sha->s[1] = 0x23925381ul;
    107     sha->s[2] = 0x11679112ul;
    108     sha->s[3] = 0xd1627e0ful;
    109     sha->s[4] = 0x97c87550ul;
    110     sha->s[5] = 0x003cc765ul;
    111     sha->s[6] = 0x90f61164ul;
    112     sha->s[7] = 0x33e9b66aul;
    113     sha->bytes = 64;
    114 }
    115 
    116 static void haskellsecp256k1_v0_1_0_schnorrsig_challenge(haskellsecp256k1_v0_1_0_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32)
    117 {
    118     unsigned char buf[32];
    119     haskellsecp256k1_v0_1_0_sha256 sha;
    120 
    121     /* tagged hash(r.x, pk.x, msg) */
    122     haskellsecp256k1_v0_1_0_schnorrsig_sha256_tagged(&sha);
    123     haskellsecp256k1_v0_1_0_sha256_write(&sha, r32, 32);
    124     haskellsecp256k1_v0_1_0_sha256_write(&sha, pubkey32, 32);
    125     haskellsecp256k1_v0_1_0_sha256_write(&sha, msg, msglen);
    126     haskellsecp256k1_v0_1_0_sha256_finalize(&sha, buf);
    127     /* Set scalar e to the challenge hash modulo the curve order as per
    128      * BIP340. */
    129     haskellsecp256k1_v0_1_0_scalar_set_b32(e, buf, NULL);
    130 }
    131 
    132 static int haskellsecp256k1_v0_1_0_schnorrsig_sign_internal(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const haskellsecp256k1_v0_1_0_keypair *keypair, haskellsecp256k1_v0_1_0_nonce_function_hardened noncefp, void *ndata) {
    133     haskellsecp256k1_v0_1_0_scalar sk;
    134     haskellsecp256k1_v0_1_0_scalar e;
    135     haskellsecp256k1_v0_1_0_scalar k;
    136     haskellsecp256k1_v0_1_0_gej rj;
    137     haskellsecp256k1_v0_1_0_ge pk;
    138     haskellsecp256k1_v0_1_0_ge r;
    139     unsigned char buf[32] = { 0 };
    140     unsigned char pk_buf[32];
    141     unsigned char seckey[32];
    142     int ret = 1;
    143 
    144     VERIFY_CHECK(ctx != NULL);
    145     ARG_CHECK(haskellsecp256k1_v0_1_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
    146     ARG_CHECK(sig64 != NULL);
    147     ARG_CHECK(msg != NULL || msglen == 0);
    148     ARG_CHECK(keypair != NULL);
    149 
    150     if (noncefp == NULL) {
    151         noncefp = haskellsecp256k1_v0_1_0_nonce_function_bip340;
    152     }
    153 
    154     ret &= haskellsecp256k1_v0_1_0_keypair_load(ctx, &sk, &pk, keypair);
    155     /* Because we are signing for a x-only pubkey, the secret key is negated
    156      * before signing if the point corresponding to the secret key does not
    157      * have an even Y. */
    158     if (haskellsecp256k1_v0_1_0_fe_is_odd(&pk.y)) {
    159         haskellsecp256k1_v0_1_0_scalar_negate(&sk, &sk);
    160     }
    161 
    162     haskellsecp256k1_v0_1_0_scalar_get_b32(seckey, &sk);
    163     haskellsecp256k1_v0_1_0_fe_get_b32(pk_buf, &pk.x);
    164     ret &= !!noncefp(buf, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
    165     haskellsecp256k1_v0_1_0_scalar_set_b32(&k, buf, NULL);
    166     ret &= !haskellsecp256k1_v0_1_0_scalar_is_zero(&k);
    167     haskellsecp256k1_v0_1_0_scalar_cmov(&k, &haskellsecp256k1_v0_1_0_scalar_one, !ret);
    168 
    169     haskellsecp256k1_v0_1_0_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k);
    170     haskellsecp256k1_v0_1_0_ge_set_gej(&r, &rj);
    171 
    172     /* We declassify r to allow using it as a branch point. This is fine
    173      * because r is not a secret. */
    174     haskellsecp256k1_v0_1_0_declassify(ctx, &r, sizeof(r));
    175     haskellsecp256k1_v0_1_0_fe_normalize_var(&r.y);
    176     if (haskellsecp256k1_v0_1_0_fe_is_odd(&r.y)) {
    177         haskellsecp256k1_v0_1_0_scalar_negate(&k, &k);
    178     }
    179     haskellsecp256k1_v0_1_0_fe_normalize_var(&r.x);
    180     haskellsecp256k1_v0_1_0_fe_get_b32(&sig64[0], &r.x);
    181 
    182     haskellsecp256k1_v0_1_0_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf);
    183     haskellsecp256k1_v0_1_0_scalar_mul(&e, &e, &sk);
    184     haskellsecp256k1_v0_1_0_scalar_add(&e, &e, &k);
    185     haskellsecp256k1_v0_1_0_scalar_get_b32(&sig64[32], &e);
    186 
    187     haskellsecp256k1_v0_1_0_memczero(sig64, 64, !ret);
    188     haskellsecp256k1_v0_1_0_scalar_clear(&k);
    189     haskellsecp256k1_v0_1_0_scalar_clear(&sk);
    190     memset(seckey, 0, sizeof(seckey));
    191 
    192     return ret;
    193 }
    194 
    195 int haskellsecp256k1_v0_1_0_schnorrsig_sign32(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *sig64, const unsigned char *msg32, const haskellsecp256k1_v0_1_0_keypair *keypair, const unsigned char *aux_rand32) {
    196     /* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */
    197     return haskellsecp256k1_v0_1_0_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, haskellsecp256k1_v0_1_0_nonce_function_bip340, (unsigned char*)aux_rand32);
    198 }
    199 
    200 int haskellsecp256k1_v0_1_0_schnorrsig_sign(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *sig64, const unsigned char *msg32, const haskellsecp256k1_v0_1_0_keypair *keypair, const unsigned char *aux_rand32) {
    201     return haskellsecp256k1_v0_1_0_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32);
    202 }
    203 
    204 int haskellsecp256k1_v0_1_0_schnorrsig_sign_custom(const haskellsecp256k1_v0_1_0_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const haskellsecp256k1_v0_1_0_keypair *keypair, haskellsecp256k1_v0_1_0_schnorrsig_extraparams *extraparams) {
    205     haskellsecp256k1_v0_1_0_nonce_function_hardened noncefp = NULL;
    206     void *ndata = NULL;
    207     VERIFY_CHECK(ctx != NULL);
    208 
    209     if (extraparams != NULL) {
    210         ARG_CHECK(haskellsecp256k1_v0_1_0_memcmp_var(extraparams->magic,
    211                                        schnorrsig_extraparams_magic,
    212                                        sizeof(extraparams->magic)) == 0);
    213         noncefp = extraparams->noncefp;
    214         ndata = extraparams->ndata;
    215     }
    216     return haskellsecp256k1_v0_1_0_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata);
    217 }
    218 
    219 int haskellsecp256k1_v0_1_0_schnorrsig_verify(const haskellsecp256k1_v0_1_0_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const haskellsecp256k1_v0_1_0_xonly_pubkey *pubkey) {
    220     haskellsecp256k1_v0_1_0_scalar s;
    221     haskellsecp256k1_v0_1_0_scalar e;
    222     haskellsecp256k1_v0_1_0_gej rj;
    223     haskellsecp256k1_v0_1_0_ge pk;
    224     haskellsecp256k1_v0_1_0_gej pkj;
    225     haskellsecp256k1_v0_1_0_fe rx;
    226     haskellsecp256k1_v0_1_0_ge r;
    227     unsigned char buf[32];
    228     int overflow;
    229 
    230     VERIFY_CHECK(ctx != NULL);
    231     ARG_CHECK(sig64 != NULL);
    232     ARG_CHECK(msg != NULL || msglen == 0);
    233     ARG_CHECK(pubkey != NULL);
    234 
    235     if (!haskellsecp256k1_v0_1_0_fe_set_b32_limit(&rx, &sig64[0])) {
    236         return 0;
    237     }
    238 
    239     haskellsecp256k1_v0_1_0_scalar_set_b32(&s, &sig64[32], &overflow);
    240     if (overflow) {
    241         return 0;
    242     }
    243 
    244     if (!haskellsecp256k1_v0_1_0_xonly_pubkey_load(ctx, &pk, pubkey)) {
    245         return 0;
    246     }
    247 
    248     /* Compute e. */
    249     haskellsecp256k1_v0_1_0_fe_get_b32(buf, &pk.x);
    250     haskellsecp256k1_v0_1_0_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf);
    251 
    252     /* Compute rj =  s*G + (-e)*pkj */
    253     haskellsecp256k1_v0_1_0_scalar_negate(&e, &e);
    254     haskellsecp256k1_v0_1_0_gej_set_ge(&pkj, &pk);
    255     haskellsecp256k1_v0_1_0_ecmult(&rj, &pkj, &e, &s);
    256 
    257     haskellsecp256k1_v0_1_0_ge_set_gej_var(&r, &rj);
    258     if (haskellsecp256k1_v0_1_0_ge_is_infinity(&r)) {
    259         return 0;
    260     }
    261 
    262     haskellsecp256k1_v0_1_0_fe_normalize_var(&r.y);
    263     return !haskellsecp256k1_v0_1_0_fe_is_odd(&r.y) &&
    264            haskellsecp256k1_v0_1_0_fe_equal(&rx, &r.x);
    265 }
    266 
    267 #endif