github.com/core-coin/go-core/v2@v2.1.9/crypto/ecies/ecies_test.go (about)

     1  // Copyright (c) 2013 Kyle Isom <kyle@tyrfingr.is>
     2  // Copyright (c) 2012 The Go Authors. All rights reserved.
     3  //
     4  // Redistribution and use in source and binary forms, with or without
     5  // modification, are permitted provided that the following conditions are
     6  // met:
     7  //
     8  //    * Redistributions of source code must retain the above copyright
     9  // notice, this list of conditions and the following disclaimer.
    10  //    * Redistributions in binary form must reproduce the above
    11  // copyright notice, this list of conditions and the following disclaimer
    12  // in the documentation and/or other materials provided with the
    13  // distribution.
    14  //    * Neither the name of Google Inc. nor the names of its
    15  // contributors may be used to endorse or promote products derived from
    16  // this software without specific prior written permission.
    17  //
    18  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    22  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    23  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    24  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    28  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    29  
    30  package ecies
    31  
    32  import (
    33  	"bytes"
    34  	"crypto/rand"
    35  	"encoding/hex"
    36  	"fmt"
    37  	"testing"
    38  
    39  	"golang.org/x/crypto/sha3"
    40  
    41  	"github.com/core-coin/go-core/v2/common"
    42  	"github.com/core-coin/go-core/v2/crypto"
    43  )
    44  
    45  func TestKDF(t *testing.T) {
    46  	tests := []struct {
    47  		length int
    48  		output []byte
    49  	}{
    50  		{6, decode("7dd366b373fd")},
    51  		{32, decode("7dd366b373fdc9b1626148e981a057b4913b0e00dec183907d22872a6b1f9db7")},
    52  		{48, decode("7dd366b373fdc9b1626148e981a057b4913b0e00dec183907d22872a6b1f9db7f489ffb85e14eb26fb5443f374a985b2")},
    53  		{64, decode("7dd366b373fdc9b1626148e981a057b4913b0e00dec183907d22872a6b1f9db7f489ffb85e14eb26fb5443f374a985b2a13189abab09aa0b497f2bcb257e6356")},
    54  	}
    55  
    56  	for _, test := range tests {
    57  		h := sha3.New256()
    58  		k := concatKDF(h, []byte("input"), nil, test.length)
    59  		if !bytes.Equal(k, test.output) {
    60  			t.Fatalf("KDF: generated key %x does not match expected output %x", k, test.output)
    61  		}
    62  	}
    63  }
    64  
    65  var ErrBadSharedKeys = fmt.Errorf("ecies: shared keys don't match")
    66  
    67  // Validate the ECDH component.
    68  func TestSharedKey(t *testing.T) {
    69  	prv1, err := crypto.GenerateKey(rand.Reader)
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	prv2, err := crypto.GenerateKey(rand.Reader)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	pub1 := crypto.DerivePublicKey(prv1)
    80  	pub2 := crypto.DerivePublicKey(prv2)
    81  
    82  	sk1 := crypto.ComputeSecret(prv1, pub2)
    83  
    84  	sk2 := crypto.ComputeSecret(prv2, pub1)
    85  
    86  	if !bytes.Equal(sk1, sk2) {
    87  		t.Fatal(ErrBadSharedKeys)
    88  	}
    89  }
    90  
    91  func TestSharedKeyPadding(t *testing.T) {
    92  	// sanity checks
    93  	prv0, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("1033b1bac4c731e800b6399a357e51cf1b20eec942aac608c90b89553003e2ed3f94bd80613ee9006b1e62b6bb45109d0db9a4833e78363991"))
    94  	prv1, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("fdf02153a9d5e3e0f3a958bbe9ee7e79eaf77a22703aee462354998ab0178f06566707c297df3510a3b071ccedac6b3154531aa51d10401868"))
    95  	pub0 := decode("2f65ab658f3b0bc9fbdea48703b9c5c0dc2151c5ae8c4b77b1e5cdaee9fa20748e01960ab51ddb118d1209f73d186f0444921ad72c7c757480")
    96  	pub1 := decode("77b1d24670fee6dd811f4f06573ce5f19844eb50cb6ce960d12bdbc8bf77be2221111cf755371d9e896e544ea2a4ebf206b775df55f5e74580")
    97  
    98  	prv0Pub := crypto.DerivePublicKey(prv0)
    99  	prv1Pub := crypto.DerivePublicKey(prv1)
   100  
   101  	if !bytes.Equal(prv0Pub[:], pub0) {
   102  		t.Errorf("mismatched prv0.X:\nhave: %x\nwant: %x\n", prv0Pub, pub0)
   103  	}
   104  	if !bytes.Equal(prv1Pub[:], pub1) {
   105  		t.Errorf("mismatched prv1.X:\nhave: %x\nwant: %x\n", prv1Pub, pub1)
   106  	}
   107  
   108  	// test shared secret generation
   109  	sk1 := crypto.ComputeSecret(prv0, prv1Pub)
   110  
   111  	sk2 := crypto.ComputeSecret(prv1, prv0Pub)
   112  
   113  	if !bytes.Equal(sk1, sk2) {
   114  		t.Fatal(ErrBadSharedKeys.Error())
   115  	}
   116  }
   117  
   118  // Benchmark the generation of P256 keys.
   119  func BenchmarkGenerateKeyP256(b *testing.B) {
   120  	for i := 0; i < b.N; i++ {
   121  		if _, err := crypto.GenerateKey(rand.Reader); err != nil {
   122  			b.Fatal(err)
   123  		}
   124  	}
   125  }
   126  
   127  // Benchmark the generation of P256 shared keys.
   128  func BenchmarkGenSharedKeyP256(b *testing.B) {
   129  	prv, err := crypto.GenerateKey(rand.Reader)
   130  	if err != nil {
   131  		b.Fatal(err)
   132  	}
   133  	b.ResetTimer()
   134  	for i := 0; i < b.N; i++ {
   135  		k := crypto.ComputeSecret(prv, crypto.DerivePublicKey(prv))
   136  		if len(k) != 0 {
   137  			b.Fatal("zero key len")
   138  		}
   139  	}
   140  }
   141  
   142  // Verify that an encrypted message can be successfully decrypted.
   143  func TestEncryptDecrypt(t *testing.T) {
   144  	prv1, err := crypto.GenerateKey(rand.Reader)
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	prv2, err := crypto.GenerateKey(rand.Reader)
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  
   154  	message := []byte("Hello, world.")
   155  	ct, err := Encrypt(rand.Reader, crypto.DerivePublicKey(prv2), message, nil, nil)
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  
   160  	pt, err := Decrypt(prv2, ct, nil, nil)
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  
   165  	if !bytes.Equal(pt, message) {
   166  		t.Fatal("ecies: plaintext doesn't match message")
   167  	}
   168  
   169  	_, err = Decrypt(prv1, ct, nil, nil)
   170  	if err == nil {
   171  		t.Fatal("ecies: encryption should not have succeeded")
   172  	}
   173  }
   174  
   175  func TestDecryptShared2(t *testing.T) {
   176  	prv, err := crypto.GenerateKey(rand.Reader)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  
   181  	message := []byte("Hello, world.")
   182  	shared2 := []byte("shared data 2")
   183  	ct, err := Encrypt(rand.Reader, crypto.DerivePublicKey(prv), message, nil, shared2)
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  
   188  	// Check that decrypting with correct shared data works.
   189  	pt, err := Decrypt(prv, ct, nil, shared2)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	if !bytes.Equal(pt, message) {
   194  		t.Fatal("ecies: plaintext doesn't match message")
   195  	}
   196  
   197  	// Decrypting without shared data or incorrect shared data fails.
   198  	if _, err = Decrypt(prv, ct, nil, nil); err == nil {
   199  		t.Fatal("ecies: decrypting without shared data didn't fail")
   200  	}
   201  	if _, err = Decrypt(prv, ct, nil, []byte("garbage")); err == nil {
   202  		t.Fatal("ecies: decrypting with incorrect shared data didn't fail")
   203  	}
   204  }
   205  
   206  func TestBox(t *testing.T) {
   207  	prv1, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("1033b1bac4c731e800b6399a357e51cf1b20eec942aac608c90b89553003e2ed3f94bd80613ee9006b1e62b6bb45109d0db9a4833e78363991"))
   208  	prv2, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("fdf02153a9d5e3e0f3a958bbe9ee7e79eaf77a22703aee462354998ab0178f06566707c297df3510a3b071ccedac6b3154531aa51d10401868"))
   209  
   210  	message := []byte("Hello, world.")
   211  	ct, err := Encrypt(rand.Reader, crypto.DerivePublicKey(prv2), message, nil, nil)
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  
   216  	pt, err := Decrypt(prv2, ct, nil, nil)
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if !bytes.Equal(pt, message) {
   221  		t.Fatal("ecies: plaintext doesn't match message")
   222  	}
   223  	if _, err = Decrypt(prv1, ct, nil, nil); err == nil {
   224  		t.Fatal("ecies: encryption should not have succeeded")
   225  	}
   226  }
   227  
   228  // Verify GenerateShared against static values - useful when
   229  // debugging changes in underlying libs
   230  func TestSharedKeyStatic(t *testing.T) {
   231  	prv1, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("1033b1bac4c731e800b6399a357e51cf1b20eec942aac608c90b89553003e2ed3f94bd80613ee9006b1e62b6bb45109d0db9a4833e78363991"))
   232  	prv2, _ := crypto.UnmarshalPrivateKey(common.Hex2Bytes("fdf02153a9d5e3e0f3a958bbe9ee7e79eaf77a22703aee462354998ab0178f06566707c297df3510a3b071ccedac6b3154531aa51d10401868"))
   233  
   234  	pub1 := crypto.DerivePublicKey(prv1)
   235  	pub2 := crypto.DerivePublicKey(prv2)
   236  
   237  	sk1 := crypto.ComputeSecret(prv1, pub2)
   238  
   239  	sk2 := crypto.ComputeSecret(prv2, pub1)
   240  
   241  	if !bytes.Equal(sk1, sk2) {
   242  		t.Fatal(ErrBadSharedKeys)
   243  	}
   244  
   245  	sk := decode("55a3895b1c32b1d9b2160d81da1f56d2f60641fc6b997adffc53b5f473e2b62a0dc65fb4aed8fddbae912864b683a29885df4bd86c1d4760")
   246  	if !bytes.Equal(sk1, sk) {
   247  		t.Fatalf("shared secret mismatch: want: %x have: %x", sk, sk1)
   248  	}
   249  }
   250  
   251  func decode(s string) []byte {
   252  	bytes, err := hex.DecodeString(s)
   253  	if err != nil {
   254  		panic(err)
   255  	}
   256  	return bytes
   257  }