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_wycheproof_generate.py (3539B)


      1 #!/usr/bin/env python3
      2 # Copyright (c) 2023 Random "Randy" Lattice and Sean Andersen
      3 # Distributed under the MIT software license, see the accompanying
      4 # file COPYING or https://www.opensource.org/licenses/mit-license.php.
      5 '''
      6 Generate a C file with ECDSA testvectors from the Wycheproof project.
      7 '''
      8 
      9 import json
     10 import sys
     11 
     12 filename_input = sys.argv[1]
     13 
     14 with open(filename_input) as f:
     15     doc = json.load(f)
     16 
     17 num_groups = len(doc['testGroups'])
     18 
     19 def to_c_array(x):
     20     if x == "":
     21         return ""
     22     s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2]))
     23     return "0x" + s
     24 
     25 
     26 num_vectors = 0
     27 offset_msg_running, offset_pk_running, offset_sig = 0, 0, 0
     28 out = ""
     29 messages = ""
     30 signatures = ""
     31 public_keys = ""
     32 cache_msgs = {}
     33 cache_public_keys = {}
     34 
     35 for i in range(num_groups):
     36     group = doc['testGroups'][i]
     37     num_tests = len(group['tests'])
     38     public_key = group['publicKey']
     39     for j in range(num_tests):
     40         test_vector = group['tests'][j]
     41         # // 2 to convert hex to byte length
     42         sig_size = len(test_vector['sig']) // 2
     43         msg_size = len(test_vector['msg']) // 2
     44 
     45         if test_vector['result'] == "invalid":
     46             expected_verify = 0
     47         elif test_vector['result'] == "valid":
     48             expected_verify = 1
     49         else:
     50             raise ValueError("invalid result field")
     51 
     52         if num_vectors != 0 and sig_size != 0:
     53             signatures += ",\n  "
     54 
     55         new_msg = False
     56         msg = to_c_array(test_vector['msg'])
     57         msg_offset = offset_msg_running
     58         # check for repeated msg
     59         if msg not in cache_msgs:
     60             if num_vectors != 0 and msg_size != 0:
     61                 messages += ",\n  "
     62             cache_msgs[msg] = offset_msg_running
     63             messages += msg
     64             new_msg = True
     65         else:
     66             msg_offset = cache_msgs[msg]
     67 
     68         new_pk = False
     69         pk = to_c_array(public_key['uncompressed'])
     70         pk_offset = offset_pk_running
     71         # check for repeated pk
     72         if pk not in cache_public_keys:
     73             if num_vectors != 0:
     74                 public_keys += ",\n  "
     75             cache_public_keys[pk] = offset_pk_running
     76             public_keys += pk
     77             new_pk = True
     78         else:
     79             pk_offset = cache_public_keys[pk]
     80 
     81         signatures += to_c_array(test_vector['sig'])
     82 
     83         out += "  /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n"
     84         out += f"  {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n"
     85         if new_msg:
     86             offset_msg_running += msg_size
     87         if new_pk:
     88             offset_pk_running += 65
     89         offset_sig += sig_size
     90         num_vectors += 1
     91 
     92 struct_definition = """
     93 typedef struct {
     94     size_t pk_offset;
     95     size_t msg_offset;
     96     size_t msg_len;
     97     size_t sig_offset;
     98     size_t sig_len;
     99     int expected_verify;
    100 } wycheproof_ecdsa_testvector;
    101 """
    102 
    103 
    104 print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */")
    105 print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})")
    106 
    107 print(struct_definition)
    108 
    109 print("static const unsigned char wycheproof_ecdsa_messages[]    = { " + messages + "};\n")
    110 print("static const unsigned char wycheproof_ecdsa_public_keys[] = { " + public_keys + "};\n")
    111 print("static const unsigned char wycheproof_ecdsa_signatures[]  = { " + signatures + "};\n")
    112 
    113 print("static const wycheproof_ecdsa_testvector testvectors[SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS] = {")
    114 print(out)
    115 print("};")