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 }