github.com/annchain/OG@v0.0.9/common/crypto/cgo_test.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build !noncgo 16 17 package crypto 18 19 import ( 20 "crypto/ecdsa" 21 "encoding/hex" 22 "fmt" 23 "github.com/annchain/OG/arefactor/og_interface" 24 "github.com/annchain/OG/arefactor/ogcrypto" 25 ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto" 26 "github.com/annchain/OG/og/types" 27 "github.com/annchain/OG/og/types/archive" 28 29 "github.com/btcsuite/btcd/btcec" 30 "math/big" 31 "testing" 32 "time" 33 ) 34 35 type SignerSecp256k1Go struct { 36 } 37 38 func (s *SignerSecp256k1Go) GetCryptoType() CryptoType { 39 return CryptoTypeSecp256k1 40 } 41 42 // Sign calculates an ECDSA signature. 43 // 44 // This function is susceptible to chosen plaintext attacks that can leak 45 // information about the private key that is used for signing. Callers must 46 // be aware that the given hash cannot be chosen by an adversery. Common 47 // solution is to hash any input before calculating the signature. 48 // 49 // The produced signature is in the [R || S || V] format where V is 0 or 1. 50 func (s *SignerSecp256k1Go) Sign(privKey PrivateKey, msg []byte) Signature { 51 prv, _ := ogcrypto2.ToECDSA(privKey.KeyBytes) 52 hash := Sha256(msg) 53 if len(hash) != 32 { 54 panic(fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))) 55 } 56 if prv.Curve != btcec.S256() { 57 panic(fmt.Errorf("private key curve is not secp256k1")) 58 } 59 key := (*btcec.PrivateKey)(prv) 60 signature, err := key.Sign(hash) 61 if err != nil { 62 panic(err) 63 } 64 sig := toByte(signature.R, signature.S) 65 // Convert to Ethereum signature format with 'recovery id' v at the end. 66 if len(sig) == og_interface.sigLength+1 { 67 v := sig[0] 68 copy(sig, sig[1:]) 69 //sig[64] = v 70 _ = v 71 } 72 //copy(sig, sig[1:]) 73 //v := sig[0] - 27 74 //sig[64] = v 75 return SignatureFromBytes(s.GetCryptoType(), sig) 76 } 77 78 func toByte(R *big.Int, S *big.Int) []byte { 79 rb := canonicalizeInt(R) 80 //sigS := sig.S 81 //if sigS.Cmp(S256().halfOrder) == 1 { 82 // sigS = new(big.Int).Sub(S256().N, sigS) 83 //} 84 sb := canonicalizeInt(S) 85 b := make([]byte, len(rb)+len(sb)) 86 copy(b, rb) 87 copy(b[len(rb):], sb) 88 return b 89 } 90 91 func canonicalizeInt(val *big.Int) []byte { 92 b := val.Bytes() 93 if len(b) == 0 { 94 b = []byte{0x00} 95 } 96 if b[0]&0x80 != 0 { 97 paddedBytes := make([]byte, len(b)+1) 98 copy(paddedBytes[1:], b) 99 b = paddedBytes 100 } 101 return b 102 } 103 104 // VerifySignature checks that the given public key created signature over hash. 105 // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. 106 // The signature should have the 64 byte [R || S] format. 107 func (s *SignerSecp256k1Go) Verify(pubKey PublicKey, signature Signature, msg []byte) bool { 108 hash := Sha256(msg) 109 signature = s.DealRecoverID(signature) 110 sigs := signature.SignatureBytes 111 sig := &btcec.Signature{R: new(big.Int).SetBytes(sigs[:32]), S: new(big.Int).SetBytes(sigs[32:])} 112 key, err := btcec.ParsePubKey(pubKey.KeyBytes, btcec.S256()) 113 if err != nil { 114 fmt.Println(err) 115 return false 116 } 117 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 118 if sig.S.Cmp(ogcrypto.secp256k1halfN) > 0 { 119 fmt.Println("sec") 120 return false 121 } 122 return sig.Verify(hash, key) 123 } 124 125 func (s *SignerSecp256k1Go) DealRecoverID(sig Signature) Signature { 126 l := len(sig.SignatureBytes) 127 if l == og_interface.sigLength+1 { 128 sig.SignatureBytes = sig.SignatureBytes[:l-1] 129 } 130 return sig 131 } 132 133 func (s *SignerSecp256k1Go) PubKey(privKey PrivateKey) PublicKey { 134 _, ecdsapub := btcec.PrivKeyFromBytes(btcec.S256(), privKey.KeyBytes) 135 pub := ogcrypto2.FromECDSAPub((*ecdsa.PublicKey)(ecdsapub)) 136 return PublicKeyFromBytes(CryptoTypeSecp256k1, pub[:]) 137 } 138 139 func TestSignerNewPrivKeyGO(t *testing.T) { 140 t.Parallel() 141 signer := ogcrypto2.SignerSecp256k1{} 142 for i := 0; i < 10; i++ { 143 pk, priv := signer.RandomKeyPair() 144 //fmt.Println(priv.String()) 145 //fmt.Println(pk.String()) 146 b := []byte("foohhhhjkhhj3488984984984jjjdjsdjks") 147 sig := signer.Sign(priv, b) 148 if !signer.Verify(pk, sig, b) { 149 t.Fatalf("vertfy failed") 150 } 151 fmt.Println(hex.EncodeToString(sig.SignatureBytes)) 152 153 signer2 := SignerSecp256k1Go{} 154 sig2 := signer2.Sign(priv, b) 155 fmt.Println(hex.EncodeToString(sig2.SignatureBytes)) 156 if !signer2.Verify(pk, sig2, b) { 157 t.Fatalf("vertfy failed") 158 } 159 fmt.Println(i) 160 } 161 162 } 163 164 func TestSignBenchMarks(t *testing.T) { 165 signer := ogcrypto2.SignerSecp256k1{} 166 pk, priv := signer.RandomKeyPair() 167 signer2 := SignerSecp256k1Go{} 168 var txs1 types.Txis 169 var txs2 types.Txis 170 N := 10000 171 172 for i := 0; i < N; i++ { 173 txs1 = append(txs1, archive.RandomTx()) 174 } 175 for i := 0; i < N; i++ { 176 txs2 = append(txs2, archive.RandomTx()) 177 } 178 fmt.Println("started") 179 start := time.Now() 180 for i := 0; i < len(txs1); i++ { 181 b := txs1[i].SignatureTargets() 182 sig := signer.Sign(priv, b) 183 txs1[i].GetBase().Signature = sig.SignatureBytes 184 //if !signer.Verify(pk, sig, b) { 185 // t.Fatalf("vertfy failed") 186 //} 187 } 188 fmt.Println("secp cgo used for signing ", time.Since(start)) 189 start = time.Now() 190 for i := 0; i < len(txs1); i++ { 191 b := txs1[i].SignatureTargets() 192 sig := signer2.Sign(priv, b) 193 txs2[i].GetBase().Signature = sig.SignatureBytes 194 //if !signer2.Verify(pk, sig, b) { 195 // t.Fatalf("vertfy failed") 196 //} 197 } 198 fmt.Println("secp go used for signing ", time.Since(start)) 199 start = time.Now() 200 for i := 0; i < len(txs2); i++ { 201 b := txs2[i].SignatureTargets() 202 sig := signer2.Sign(priv, b) 203 txs2[i].GetBase().Signature = sig.SignatureBytes 204 //if !signer2.Verify(pk, sig, b) { 205 // t.Fatalf("vertfy failed") 206 //} 207 } 208 fmt.Println("secp go used for signing ", time.Since(start)) 209 start = time.Now() 210 for i := 0; i < len(txs2); i++ { 211 b := txs2[i].SignatureTargets() 212 sig := signer.Sign(priv, b) 213 txs2[i].GetBase().Signature = sig.SignatureBytes 214 //if !signer.Verify(pk, sig, b) { 215 // t.Fatalf("vertfy failed") 216 //} 217 } 218 fmt.Println("secp cgo used for signing ", time.Since(start)) 219 start = time.Now() 220 for i := 0; i < len(txs1); i++ { 221 b := txs1[i].SignatureTargets() 222 sig := txs1[i].GetBase().Signature 223 if !signer2.Verify(pk, SignatureFromBytes(CryptoTypeSecp256k1, sig), b) { 224 t.Fatalf("vertfy failed") 225 } 226 } 227 fmt.Println("secp go used for verifying ", time.Since(start)) 228 start = time.Now() 229 for i := 0; i < len(txs1); i++ { 230 b := txs1[i].SignatureTargets() 231 sig := txs1[i].GetBase().Signature 232 if !signer.Verify(pk, SignatureFromBytes(CryptoTypeSecp256k1, sig), b) { 233 t.Fatalf("vertfy failed") 234 } 235 } 236 fmt.Println("secp cgo used for verifying ", time.Since(start)) 237 start = time.Now() 238 for i := 0; i < len(txs1); i++ { 239 b := txs2[i].SignatureTargets() 240 sig := txs2[i].GetBase().Signature 241 if !signer.Verify(pk, SignatureFromBytes(CryptoTypeSecp256k1, sig), b) { 242 t.Fatalf("vertfy failed") 243 } 244 } 245 fmt.Println("secp cgo used for verifying ", time.Since(start)) 246 start = time.Now() 247 for i := 0; i < len(txs1); i++ { 248 b := txs1[i].SignatureTargets() 249 sig := txs1[i].GetBase().Signature 250 if !signer2.Verify(pk, SignatureFromBytes(CryptoTypeSecp256k1, sig), b) { 251 t.Fatalf("vertfy failed") 252 } 253 } 254 fmt.Println("secp go used for verifying ", time.Since(start)) 255 256 }