github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/ed25519/ed25519_test.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ed25519
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"compress/gzip"
    11  	"crypto"
    12  	"crypto/internal/boring"
    13  	"crypto/rand"
    14  	"encoding/hex"
    15  	"internal/testenv"
    16  	"os"
    17  	"strings"
    18  	"testing"
    19  )
    20  
    21  type zeroReader struct{}
    22  
    23  func (zeroReader) Read(buf []byte) (int, error) {
    24  	for i := range buf {
    25  		buf[i] = 0
    26  	}
    27  	return len(buf), nil
    28  }
    29  
    30  func TestSignVerify(t *testing.T) {
    31  	var zero zeroReader
    32  	public, private, _ := GenerateKey(zero)
    33  
    34  	message := []byte("test message")
    35  	sig := Sign(private, message)
    36  	if !Verify(public, message, sig) {
    37  		t.Errorf("valid signature rejected")
    38  	}
    39  
    40  	wrongMessage := []byte("wrong message")
    41  	if Verify(public, wrongMessage, sig) {
    42  		t.Errorf("signature of different message accepted")
    43  	}
    44  }
    45  
    46  func TestCryptoSigner(t *testing.T) {
    47  	var zero zeroReader
    48  	public, private, _ := GenerateKey(zero)
    49  
    50  	signer := crypto.Signer(private)
    51  
    52  	publicInterface := signer.Public()
    53  	public2, ok := publicInterface.(PublicKey)
    54  	if !ok {
    55  		t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
    56  	}
    57  
    58  	if !bytes.Equal(public, public2) {
    59  		t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
    60  	}
    61  
    62  	message := []byte("message")
    63  	var noHash crypto.Hash
    64  	signature, err := signer.Sign(zero, message, noHash)
    65  	if err != nil {
    66  		t.Fatalf("error from Sign(): %s", err)
    67  	}
    68  
    69  	if !Verify(public, message, signature) {
    70  		t.Errorf("Verify failed on signature from Sign()")
    71  	}
    72  }
    73  
    74  func TestEqual(t *testing.T) {
    75  	public, private, _ := GenerateKey(rand.Reader)
    76  
    77  	if !public.Equal(public) {
    78  		t.Errorf("public key is not equal to itself: %q", public)
    79  	}
    80  	if !public.Equal(crypto.Signer(private).Public()) {
    81  		t.Errorf("private.Public() is not Equal to public: %q", public)
    82  	}
    83  	if !private.Equal(private) {
    84  		t.Errorf("private key is not equal to itself: %q", private)
    85  	}
    86  
    87  	otherPub, otherPriv, _ := GenerateKey(rand.Reader)
    88  	if public.Equal(otherPub) {
    89  		t.Errorf("different public keys are Equal")
    90  	}
    91  	if private.Equal(otherPriv) {
    92  		t.Errorf("different private keys are Equal")
    93  	}
    94  }
    95  
    96  func TestGolden(t *testing.T) {
    97  	// sign.input.gz is a selection of test cases from
    98  	// https://ed25519.cr.yp.to/python/sign.input
    99  	testDataZ, err := os.Open("testdata/sign.input.gz")
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	defer testDataZ.Close()
   104  	testData, err := gzip.NewReader(testDataZ)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	defer testData.Close()
   109  
   110  	scanner := bufio.NewScanner(testData)
   111  	lineNo := 0
   112  
   113  	for scanner.Scan() {
   114  		lineNo++
   115  
   116  		line := scanner.Text()
   117  		parts := strings.Split(line, ":")
   118  		if len(parts) != 5 {
   119  			t.Fatalf("bad number of parts on line %d", lineNo)
   120  		}
   121  
   122  		privBytes, _ := hex.DecodeString(parts[0])
   123  		pubKey, _ := hex.DecodeString(parts[1])
   124  		msg, _ := hex.DecodeString(parts[2])
   125  		sig, _ := hex.DecodeString(parts[3])
   126  		// The signatures in the test vectors also include the message
   127  		// at the end, but we just want R and S.
   128  		sig = sig[:SignatureSize]
   129  
   130  		if l := len(pubKey); l != PublicKeySize {
   131  			t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
   132  		}
   133  
   134  		var priv [PrivateKeySize]byte
   135  		copy(priv[:], privBytes)
   136  		copy(priv[32:], pubKey)
   137  
   138  		sig2 := Sign(priv[:], msg)
   139  		if !bytes.Equal(sig, sig2[:]) {
   140  			t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
   141  		}
   142  
   143  		if !Verify(pubKey, msg, sig2) {
   144  			t.Errorf("signature failed to verify on line %d", lineNo)
   145  		}
   146  
   147  		priv2 := NewKeyFromSeed(priv[:32])
   148  		if !bytes.Equal(priv[:], priv2) {
   149  			t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
   150  		}
   151  
   152  		if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
   153  			t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
   154  		}
   155  
   156  		if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
   157  			t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
   158  		}
   159  	}
   160  
   161  	if err := scanner.Err(); err != nil {
   162  		t.Fatalf("error reading test data: %s", err)
   163  	}
   164  }
   165  
   166  func TestMalleability(t *testing.T) {
   167  	// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
   168  	// that s be in [0, order). This prevents someone from adding a multiple of
   169  	// order to s and obtaining a second valid signature for the same message.
   170  	msg := []byte{0x54, 0x65, 0x73, 0x74}
   171  	sig := []byte{
   172  		0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
   173  		0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
   174  		0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
   175  		0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
   176  		0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
   177  		0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
   178  	}
   179  	publicKey := []byte{
   180  		0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
   181  		0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
   182  		0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
   183  	}
   184  
   185  	if Verify(publicKey, msg, sig) {
   186  		t.Fatal("non-canonical signature accepted")
   187  	}
   188  }
   189  
   190  func TestAllocations(t *testing.T) {
   191  	if boring.Enabled {
   192  		t.Skip("skipping allocations test with BoringCrypto")
   193  	}
   194  	testenv.SkipIfOptimizationOff(t)
   195  
   196  	if allocs := testing.AllocsPerRun(100, func() {
   197  		seed := make([]byte, SeedSize)
   198  		message := []byte("Hello, world!")
   199  		priv := NewKeyFromSeed(seed)
   200  		pub := priv.Public().(PublicKey)
   201  		signature := Sign(priv, message)
   202  		if !Verify(pub, message, signature) {
   203  			t.Fatal("signature didn't verify")
   204  		}
   205  	}); allocs > 0 {
   206  		t.Errorf("expected zero allocations, got %0.1f", allocs)
   207  	}
   208  }
   209  
   210  func BenchmarkKeyGeneration(b *testing.B) {
   211  	var zero zeroReader
   212  	for i := 0; i < b.N; i++ {
   213  		if _, _, err := GenerateKey(zero); err != nil {
   214  			b.Fatal(err)
   215  		}
   216  	}
   217  }
   218  
   219  func BenchmarkNewKeyFromSeed(b *testing.B) {
   220  	seed := make([]byte, SeedSize)
   221  	for i := 0; i < b.N; i++ {
   222  		_ = NewKeyFromSeed(seed)
   223  	}
   224  }
   225  
   226  func BenchmarkSigning(b *testing.B) {
   227  	var zero zeroReader
   228  	_, priv, err := GenerateKey(zero)
   229  	if err != nil {
   230  		b.Fatal(err)
   231  	}
   232  	message := []byte("Hello, world!")
   233  	b.ResetTimer()
   234  	for i := 0; i < b.N; i++ {
   235  		Sign(priv, message)
   236  	}
   237  }
   238  
   239  func BenchmarkVerification(b *testing.B) {
   240  	var zero zeroReader
   241  	pub, priv, err := GenerateKey(zero)
   242  	if err != nil {
   243  		b.Fatal(err)
   244  	}
   245  	message := []byte("Hello, world!")
   246  	signature := Sign(priv, message)
   247  	b.ResetTimer()
   248  	for i := 0; i < b.N; i++ {
   249  		Verify(pub, message, signature)
   250  	}
   251  }