github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 "crypto/sha512" 15 "encoding/hex" 16 "internal/testenv" 17 "log" 18 "os" 19 "strings" 20 "testing" 21 ) 22 23 func Example_ed25519ctx() { 24 pub, priv, err := GenerateKey(nil) 25 if err != nil { 26 log.Fatal(err) 27 } 28 29 msg := []byte("The quick brown fox jumps over the lazy dog") 30 31 sig, err := priv.Sign(nil, msg, &Options{ 32 Context: "Example_ed25519ctx", 33 }) 34 if err != nil { 35 log.Fatal(err) 36 } 37 38 if err := VerifyWithOptions(pub, msg, sig, &Options{ 39 Context: "Example_ed25519ctx", 40 }); err != nil { 41 log.Fatal("invalid signature") 42 } 43 } 44 45 type zeroReader struct{} 46 47 func (zeroReader) Read(buf []byte) (int, error) { 48 for i := range buf { 49 buf[i] = 0 50 } 51 return len(buf), nil 52 } 53 54 func TestSignVerify(t *testing.T) { 55 var zero zeroReader 56 public, private, _ := GenerateKey(zero) 57 58 message := []byte("test message") 59 sig := Sign(private, message) 60 if !Verify(public, message, sig) { 61 t.Errorf("valid signature rejected") 62 } 63 64 wrongMessage := []byte("wrong message") 65 if Verify(public, wrongMessage, sig) { 66 t.Errorf("signature of different message accepted") 67 } 68 } 69 70 func TestSignVerifyHashed(t *testing.T) { 71 // From RFC 8032, Section 7.3 72 key, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf") 73 expectedSig, _ := hex.DecodeString("98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406") 74 message, _ := hex.DecodeString("616263") 75 76 private := PrivateKey(key) 77 public := private.Public().(PublicKey) 78 hash := sha512.Sum512(message) 79 sig, err := private.Sign(nil, hash[:], crypto.SHA512) 80 if err != nil { 81 t.Fatal(err) 82 } 83 if !bytes.Equal(sig, expectedSig) { 84 t.Error("signature doesn't match test vector") 85 } 86 sig, err = private.Sign(nil, hash[:], &Options{Hash: crypto.SHA512}) 87 if err != nil { 88 t.Fatal(err) 89 } 90 if !bytes.Equal(sig, expectedSig) { 91 t.Error("signature doesn't match test vector") 92 } 93 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}); err != nil { 94 t.Errorf("valid signature rejected: %v", err) 95 } 96 97 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA256}); err == nil { 98 t.Errorf("expected error for wrong hash") 99 } 100 101 wrongHash := sha512.Sum512([]byte("wrong message")) 102 if VerifyWithOptions(public, wrongHash[:], sig, &Options{Hash: crypto.SHA512}) == nil { 103 t.Errorf("signature of different message accepted") 104 } 105 106 sig[0] ^= 0xff 107 if VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}) == nil { 108 t.Errorf("invalid signature accepted") 109 } 110 sig[0] ^= 0xff 111 sig[SignatureSize-1] ^= 0xff 112 if VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512}) == nil { 113 t.Errorf("invalid signature accepted") 114 } 115 116 // The RFC provides no test vectors for Ed25519ph with context, so just sign 117 // and verify something. 118 sig, err = private.Sign(nil, hash[:], &Options{Hash: crypto.SHA512, Context: "123"}) 119 if err != nil { 120 t.Fatal(err) 121 } 122 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512, Context: "123"}); err != nil { 123 t.Errorf("valid signature rejected: %v", err) 124 } 125 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA512, Context: "321"}); err == nil { 126 t.Errorf("expected error for wrong context") 127 } 128 if err := VerifyWithOptions(public, hash[:], sig, &Options{Hash: crypto.SHA256, Context: "123"}); err == nil { 129 t.Errorf("expected error for wrong hash") 130 } 131 } 132 133 func TestSignVerifyContext(t *testing.T) { 134 // From RFC 8032, Section 7.2 135 key, _ := hex.DecodeString("0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292") 136 expectedSig, _ := hex.DecodeString("55a4cc2f70a54e04288c5f4cd1e45a7bb520b36292911876cada7323198dd87a8b36950b95130022907a7fb7c4e9b2d5f6cca685a587b4b21f4b888e4e7edb0d") 137 message, _ := hex.DecodeString("f726936d19c800494e3fdaff20b276a8") 138 context := "foo" 139 140 private := PrivateKey(key) 141 public := private.Public().(PublicKey) 142 sig, err := private.Sign(nil, message, &Options{Context: context}) 143 if err != nil { 144 t.Fatal(err) 145 } 146 if !bytes.Equal(sig, expectedSig) { 147 t.Error("signature doesn't match test vector") 148 } 149 if err := VerifyWithOptions(public, message, sig, &Options{Context: context}); err != nil { 150 t.Errorf("valid signature rejected: %v", err) 151 } 152 153 if VerifyWithOptions(public, []byte("bar"), sig, &Options{Context: context}) == nil { 154 t.Errorf("signature of different message accepted") 155 } 156 if VerifyWithOptions(public, message, sig, &Options{Context: "bar"}) == nil { 157 t.Errorf("signature with different context accepted") 158 } 159 160 sig[0] ^= 0xff 161 if VerifyWithOptions(public, message, sig, &Options{Context: context}) == nil { 162 t.Errorf("invalid signature accepted") 163 } 164 sig[0] ^= 0xff 165 sig[SignatureSize-1] ^= 0xff 166 if VerifyWithOptions(public, message, sig, &Options{Context: context}) == nil { 167 t.Errorf("invalid signature accepted") 168 } 169 } 170 171 func TestCryptoSigner(t *testing.T) { 172 var zero zeroReader 173 public, private, _ := GenerateKey(zero) 174 175 signer := crypto.Signer(private) 176 177 publicInterface := signer.Public() 178 public2, ok := publicInterface.(PublicKey) 179 if !ok { 180 t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) 181 } 182 183 if !bytes.Equal(public, public2) { 184 t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) 185 } 186 187 message := []byte("message") 188 var noHash crypto.Hash 189 signature, err := signer.Sign(zero, message, noHash) 190 if err != nil { 191 t.Fatalf("error from Sign(): %s", err) 192 } 193 194 signature2, err := signer.Sign(zero, message, &Options{Hash: noHash}) 195 if err != nil { 196 t.Fatalf("error from Sign(): %s", err) 197 } 198 if !bytes.Equal(signature, signature2) { 199 t.Errorf("signatures keys do not match") 200 } 201 202 if !Verify(public, message, signature) { 203 t.Errorf("Verify failed on signature from Sign()") 204 } 205 } 206 207 func TestEqual(t *testing.T) { 208 public, private, _ := GenerateKey(rand.Reader) 209 210 if !public.Equal(public) { 211 t.Errorf("public key is not equal to itself: %q", public) 212 } 213 if !public.Equal(crypto.Signer(private).Public()) { 214 t.Errorf("private.Public() is not Equal to public: %q", public) 215 } 216 if !private.Equal(private) { 217 t.Errorf("private key is not equal to itself: %q", private) 218 } 219 220 otherPub, otherPriv, _ := GenerateKey(rand.Reader) 221 if public.Equal(otherPub) { 222 t.Errorf("different public keys are Equal") 223 } 224 if private.Equal(otherPriv) { 225 t.Errorf("different private keys are Equal") 226 } 227 } 228 229 func TestGolden(t *testing.T) { 230 // sign.input.gz is a selection of test cases from 231 // https://ed25519.cr.yp.to/python/sign.input 232 testDataZ, err := os.Open("testdata/sign.input.gz") 233 if err != nil { 234 t.Fatal(err) 235 } 236 defer testDataZ.Close() 237 testData, err := gzip.NewReader(testDataZ) 238 if err != nil { 239 t.Fatal(err) 240 } 241 defer testData.Close() 242 243 scanner := bufio.NewScanner(testData) 244 lineNo := 0 245 246 for scanner.Scan() { 247 lineNo++ 248 249 line := scanner.Text() 250 parts := strings.Split(line, ":") 251 if len(parts) != 5 { 252 t.Fatalf("bad number of parts on line %d", lineNo) 253 } 254 255 privBytes, _ := hex.DecodeString(parts[0]) 256 pubKey, _ := hex.DecodeString(parts[1]) 257 msg, _ := hex.DecodeString(parts[2]) 258 sig, _ := hex.DecodeString(parts[3]) 259 // The signatures in the test vectors also include the message 260 // at the end, but we just want R and S. 261 sig = sig[:SignatureSize] 262 263 if l := len(pubKey); l != PublicKeySize { 264 t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) 265 } 266 267 var priv [PrivateKeySize]byte 268 copy(priv[:], privBytes) 269 copy(priv[32:], pubKey) 270 271 sig2 := Sign(priv[:], msg) 272 if !bytes.Equal(sig, sig2[:]) { 273 t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) 274 } 275 276 if !Verify(pubKey, msg, sig2) { 277 t.Errorf("signature failed to verify on line %d", lineNo) 278 } 279 280 priv2 := NewKeyFromSeed(priv[:32]) 281 if !bytes.Equal(priv[:], priv2) { 282 t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) 283 } 284 285 if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { 286 t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) 287 } 288 289 if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) { 290 t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed) 291 } 292 } 293 294 if err := scanner.Err(); err != nil { 295 t.Fatalf("error reading test data: %s", err) 296 } 297 } 298 299 func TestMalleability(t *testing.T) { 300 // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test 301 // that s be in [0, order). This prevents someone from adding a multiple of 302 // order to s and obtaining a second valid signature for the same message. 303 msg := []byte{0x54, 0x65, 0x73, 0x74} 304 sig := []byte{ 305 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, 306 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, 307 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, 308 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, 309 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, 310 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, 311 } 312 publicKey := []byte{ 313 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, 314 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, 315 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, 316 } 317 318 if Verify(publicKey, msg, sig) { 319 t.Fatal("non-canonical signature accepted") 320 } 321 } 322 323 func TestAllocations(t *testing.T) { 324 if boring.Enabled { 325 t.Skip("skipping allocations test with BoringCrypto") 326 } 327 testenv.SkipIfOptimizationOff(t) 328 329 if allocs := testing.AllocsPerRun(100, func() { 330 seed := make([]byte, SeedSize) 331 message := []byte("Hello, world!") 332 priv := NewKeyFromSeed(seed) 333 pub := priv.Public().(PublicKey) 334 signature := Sign(priv, message) 335 if !Verify(pub, message, signature) { 336 t.Fatal("signature didn't verify") 337 } 338 }); allocs > 0 { 339 t.Errorf("expected zero allocations, got %0.1f", allocs) 340 } 341 } 342 343 func BenchmarkKeyGeneration(b *testing.B) { 344 var zero zeroReader 345 for i := 0; i < b.N; i++ { 346 if _, _, err := GenerateKey(zero); err != nil { 347 b.Fatal(err) 348 } 349 } 350 } 351 352 func BenchmarkNewKeyFromSeed(b *testing.B) { 353 seed := make([]byte, SeedSize) 354 for i := 0; i < b.N; i++ { 355 _ = NewKeyFromSeed(seed) 356 } 357 } 358 359 func BenchmarkSigning(b *testing.B) { 360 var zero zeroReader 361 _, priv, err := GenerateKey(zero) 362 if err != nil { 363 b.Fatal(err) 364 } 365 message := []byte("Hello, world!") 366 b.ResetTimer() 367 for i := 0; i < b.N; i++ { 368 Sign(priv, message) 369 } 370 } 371 372 func BenchmarkVerification(b *testing.B) { 373 var zero zeroReader 374 pub, priv, err := GenerateKey(zero) 375 if err != nil { 376 b.Fatal(err) 377 } 378 message := []byte("Hello, world!") 379 signature := Sign(priv, message) 380 b.ResetTimer() 381 for i := 0; i < b.N; i++ { 382 Verify(pub, message, signature) 383 } 384 }