github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/others/cgo/sipasec/sipasec.go (about)

     1  package sipasec
     2  
     3  /*
     4  #include <stdio.h>
     5  #include <string.h>
     6  #include "secp256k1.h"
     7  #include "secp256k1_schnorrsig.h" // make sure to build libsecp256k1 with: ./configure --enable-module-schnorrsig --enable-experimental
     8  
     9  static secp256k1_context *ctx;
    10  
    11  static void secp256k1_start() {
    12  	ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
    13  }
    14  
    15  static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
    16      size_t rpos, rlen, spos, slen;
    17      size_t pos = 0;
    18      size_t lenbyte;
    19      unsigned char tmpsig[64] = {0};
    20      int overflow = 0;
    21  
    22      secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
    23  
    24      if (pos == inputlen || input[pos] != 0x30) {
    25          return 0;
    26      }
    27      pos++;
    28  
    29      if (pos == inputlen) {
    30          return 0;
    31      }
    32      lenbyte = input[pos++];
    33      if (lenbyte & 0x80) {
    34          lenbyte -= 0x80;
    35          if (pos + lenbyte > inputlen) {
    36              return 0;
    37          }
    38          pos += lenbyte;
    39      }
    40  
    41      if (pos == inputlen || input[pos] != 0x02) {
    42          return 0;
    43      }
    44      pos++;
    45  
    46      if (pos == inputlen) {
    47          return 0;
    48      }
    49      lenbyte = input[pos++];
    50      if (lenbyte & 0x80) {
    51          lenbyte -= 0x80;
    52          if (pos + lenbyte > inputlen) {
    53              return 0;
    54          }
    55          while (lenbyte > 0 && input[pos] == 0) {
    56              pos++;
    57              lenbyte--;
    58          }
    59          if (lenbyte >= sizeof(size_t)) {
    60              return 0;
    61          }
    62          rlen = 0;
    63          while (lenbyte > 0) {
    64              rlen = (rlen << 8) + input[pos];
    65              pos++;
    66              lenbyte--;
    67          }
    68      } else {
    69          rlen = lenbyte;
    70      }
    71      if (rlen > inputlen - pos) {
    72          return 0;
    73      }
    74      rpos = pos;
    75      pos += rlen;
    76  
    77      if (pos == inputlen || input[pos] != 0x02) {
    78          return 0;
    79      }
    80      pos++;
    81  
    82      if (pos == inputlen) {
    83          return 0;
    84      }
    85      lenbyte = input[pos++];
    86      if (lenbyte & 0x80) {
    87          lenbyte -= 0x80;
    88          if (pos + lenbyte > inputlen) {
    89              return 0;
    90          }
    91          while (lenbyte > 0 && input[pos] == 0) {
    92              pos++;
    93              lenbyte--;
    94          }
    95          if (lenbyte >= sizeof(size_t)) {
    96              return 0;
    97          }
    98          slen = 0;
    99          while (lenbyte > 0) {
   100              slen = (slen << 8) + input[pos];
   101              pos++;
   102              lenbyte--;
   103          }
   104      } else {
   105          slen = lenbyte;
   106      }
   107      if (slen > inputlen - pos) {
   108          return 0;
   109      }
   110      spos = pos;
   111      pos += slen;
   112  
   113      while (rlen > 0 && input[rpos] == 0) {
   114          rlen--;
   115          rpos++;
   116      }
   117      if (rlen > 32) {
   118          overflow = 1;
   119      } else {
   120          memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
   121      }
   122  
   123      while (slen > 0 && input[spos] == 0) {
   124          slen--;
   125          spos++;
   126      }
   127      if (slen > 32) {
   128          overflow = 1;
   129      } else {
   130          memcpy(tmpsig + 64 - slen, input + spos, slen);
   131      }
   132  
   133      if (!overflow) {
   134          overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
   135      }
   136      if (overflow) {
   137          memset(tmpsig, 0, 64);
   138          secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
   139      }
   140      return 1;
   141  }
   142  
   143  
   144  static int secp256k1_verify(unsigned char *msg, unsigned char *sig, int siglen, unsigned char *pk, int pklen) {
   145  	int result;
   146      secp256k1_pubkey pubkey;
   147  	secp256k1_ecdsa_signature _sig;
   148  
   149  	if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pk, pklen)) {
   150  		return -1;
   151  	}
   152  	if (!ecdsa_signature_parse_der_lax(ctx, &_sig, sig, siglen)) {
   153  		return -1;
   154  	}
   155  
   156  	secp256k1_ecdsa_signature_normalize(ctx, &_sig, &_sig);
   157  	result = secp256k1_ecdsa_verify(ctx, &_sig, msg, &pubkey);
   158  
   159  	return result;
   160  }
   161  
   162  static int gocoin_schnorr_verify(unsigned char *msg, unsigned char *sig, unsigned char *pk) {
   163  	secp256k1_xonly_pubkey pubkey;
   164  	if (!secp256k1_xonly_pubkey_parse(ctx, &pubkey, pk)) return 0;
   165  	//printf("pubkey: %02x%02x.. ==> %02x%02x... %02x%02x...\n", pk[0], pk[1], pubkey.data[0], pubkey.data[1], pubkey.data[32], pubkey.data[33]);
   166  	return secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &pubkey);
   167  }
   168  
   169  static int check_pay_to_contract(unsigned char *m_keydata, unsigned char *base, unsigned char *hash, int parity) {
   170      secp256k1_xonly_pubkey base_point;
   171      if (!secp256k1_xonly_pubkey_parse(ctx, &base_point, base)) return 0;
   172      return secp256k1_xonly_pubkey_tweak_add_check(ctx, m_keydata, parity, &base_point, hash);
   173  }
   174  
   175  */
   176  import "C"
   177  import "unsafe"
   178  
   179  // EC_Verify verifies an ECDSA signature.
   180  func EC_Verify(pkey, sign, hash []byte) int {
   181  	return int(C.secp256k1_verify((*C.uchar)(unsafe.Pointer(&hash[0])),
   182  		(*C.uchar)(unsafe.Pointer(&sign[0])), C.int(len(sign)),
   183  		(*C.uchar)(unsafe.Pointer(&pkey[0])), C.int(len(pkey))))
   184  }
   185  
   186  func Schnorr_Verify(pkey, sign, msg []byte) int {
   187  	return int(C.gocoin_schnorr_verify((*C.uchar)(unsafe.Pointer(&msg[0])),
   188  		(*C.uchar)(unsafe.Pointer(&sign[0])), (*C.uchar)(unsafe.Pointer(&pkey[0]))))
   189  }
   190  
   191  func CheckPayToContract(m_keydata, base, hash []byte, parity bool) int {
   192  	var par C.int
   193  	if parity {
   194  		par = 1
   195  	}
   196  	return int(C.check_pay_to_contract((*C.uchar)(unsafe.Pointer(&m_keydata[0])),
   197  		(*C.uchar)(unsafe.Pointer(&base[0])), (*C.uchar)(unsafe.Pointer(&hash[0])), par))
   198  }
   199  
   200  func init() {
   201  	C.secp256k1_start()
   202  }