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 }