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