github.com/klaytn/klaytn@v1.12.1/crypto/secp256k1/schnorr_test.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  //
     3  // This file is part of the klaytn library.
     4  //
     5  // The klaytn library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The klaytn library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package secp256k1
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/hex"
    23  	"fmt"
    24  	"testing"
    25  	"time"
    26  )
    27  
    28  func TestSingle(t *testing.T) {
    29  	m := hash([]byte("hello world"))
    30  
    31  	G := S256()
    32  	x, _ := hex.DecodeString("4f52e337ad8bf1ce10cbb72ab91d9954474cea39811040df5558297df3e3c1bf")
    33  	P := G.Marshal(G.ScalarBaseMult(x))
    34  
    35  	R, s := SchnorrSignSingle(G, m, x, P)
    36  
    37  	start := time.Now()
    38  	result := SchnorrVerify(G, m, R, s, P)
    39  	elapsed := time.Since(start)
    40  
    41  	fmt.Printf("Go Imp: %d us\n", elapsed/1000)
    42  	if !result {
    43  		t.Fail()
    44  	}
    45  
    46  	start = time.Now()
    47  	result = SchnorrVerifyNative(m, R, s, P)
    48  	elapsed = time.Since(start)
    49  
    50  	fmt.Printf("C Imp: %d us\n", elapsed/1000)
    51  	if !result {
    52  		t.Fail()
    53  	}
    54  }
    55  
    56  func TestDouble(t *testing.T) {
    57  	msg := hash([]byte("hello"))
    58  	G := S256()
    59  
    60  	// For two arbitrary SECP256k1 private keys
    61  	x0, _ := hex.DecodeString("4f52e337ad8bf1ce10cbb72ab91d9954474cea39811040df5558297df3e3c1bf") // Alice
    62  	x1, _ := hex.DecodeString("54390f30fbe7094a5080cd4dcc3f91869faaca23a43aed2eb20a426db067b7c9") // Bob
    63  
    64  	// Derive public keys from the private keys; P0 = Alice's pubkey, P1 = Bob's pubkey
    65  	P0x, P0y := G.ScalarBaseMult(x0)
    66  	P0 := G.Marshal(P0x, P0y)
    67  
    68  	P1x, P1y := G.ScalarBaseMult(x1)
    69  	P1 := G.Marshal(P1x, P1y)
    70  
    71  	// Begin the signing party
    72  	Q0, R0, y0 := SchnorrSignMultiBootstrap(G, msg, x0, P0, P1) // Alice
    73  	Q1, R1, y1 := SchnorrSignMultiBootstrap(G, msg, x1, P1, P0) // Bob
    74  
    75  	// Unpack the masked public keys
    76  	Q0x, Q0y := G.Unmarshal(Q0)
    77  	Q1x, Q1y := G.Unmarshal(Q1)
    78  
    79  	// Combine them to get the common public key P
    80  	P := G.Marshal(G.Add(Q0x, Q0y, Q1x, Q1y))
    81  
    82  	// Unpack R values
    83  	R0x, R0y := G.Unmarshal(R0)
    84  	R1x, R1y := G.Unmarshal(R1)
    85  
    86  	// Combine them to get the R; this is the first chunk of the signature signed by both Alice and Bob
    87  	R := G.Marshal(G.Add(R0x, R0y, R1x, R1y))
    88  
    89  	// Now both Alice and Bob know P and R; let's get the rest --- s
    90  	s0 := SchnorrSignMultiComputeS(msg, P, R, y0)
    91  	s1 := SchnorrSignMultiComputeS(msg, P, R, y1)
    92  
    93  	// Let's combine this together
    94  	s := ScAdd(s0, s1)
    95  
    96  	// At this point, we have (R, s), a complete Schnorr signature signed by both Alice and Bob.
    97  	// We can verify (R, s) by checking R = s * G + H(m || P || R) * P.
    98  
    99  	// Let's verify the signature
   100  	i := int64(0)
   101  	var start time.Time
   102  	var elapsed, sumNative, sumGo time.Duration
   103  
   104  	for ; i < 2000; i++ {
   105  		// Run verification using pure Go impl
   106  		start = time.Now()
   107  
   108  		if !SchnorrVerify(G, msg, R, s, P) {
   109  			t.Fail()
   110  		}
   111  
   112  		elapsed = time.Since(start)
   113  		sumGo += elapsed
   114  
   115  		// Run verification using native C impl
   116  		start = time.Now()
   117  		if !SchnorrVerifyNative(msg, R, s, P) {
   118  			t.Fail()
   119  		}
   120  
   121  		elapsed = time.Since(start)
   122  		sumNative += elapsed
   123  	}
   124  
   125  	fmt.Printf("schnorr_go = %d us\n", sumGo.Nanoseconds()/i/1000)
   126  	fmt.Printf("schnorr_native = %d us\n", sumNative.Nanoseconds()/i/1000)
   127  }
   128  
   129  func TestScPointMulTest(t *testing.T) {
   130  	scalar := hash([]byte("hello"))
   131  	G := S256()
   132  
   133  	P0x, P0y := G.ScalarBaseMult(scalar)
   134  	P := G.Marshal(P0x, P0y)
   135  
   136  	pureGo := G.Marshal(G.ScalarMult(P0x, P0y, scalar))
   137  	cImp := ScPointMul(P, scalar)
   138  
   139  	if !bytes.Equal(pureGo, cImp) {
   140  		t.Fail()
   141  	}
   142  }
   143  
   144  func TestScBaseMultTest(t *testing.T) {
   145  	scalar := hash([]byte("hello"))
   146  	G := S256()
   147  
   148  	pureGo := G.Marshal(G.ScalarBaseMult(scalar))
   149  	cImp := ScBaseMul(scalar)
   150  
   151  	if !bytes.Equal(pureGo, cImp) {
   152  		t.Fail()
   153  	}
   154  }
   155  
   156  func TestComputeC(t *testing.T) {
   157  	G := S256()
   158  
   159  	x0, _ := hex.DecodeString("4f52e337ad8bf1ce10cbb72ab91d9954474cea39811040df5558297df3e3c1bf")
   160  	x1, _ := hex.DecodeString("54390f30fbe7094a5080cd4dcc3f91869faaca23a43aed2eb20a426db067b7c9")
   161  
   162  	P0x, P0y := G.ScalarBaseMult(x0)
   163  	P0 := G.Marshal(P0x, P0y)
   164  
   165  	P1x, P1y := G.ScalarBaseMult(x1)
   166  	P1 := G.Marshal(P1x, P1y)
   167  
   168  	C := ComputeC(P0, P1)
   169  	K := ComputeC(P1, P0)
   170  
   171  	if !bytes.Equal(C, K) {
   172  		t.Fail()
   173  	}
   174  }