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  }