github.com/cloudflare/circl@v1.5.0/sign/ed25519/extra_test.go (about) 1 package ed25519_test 2 3 import ( 4 "bytes" 5 "crypto" 6 "crypto/rand" 7 "errors" 8 "fmt" 9 "testing" 10 11 "github.com/cloudflare/circl/internal/test" 12 "github.com/cloudflare/circl/sign/ed25519" 13 ) 14 15 func TestWrongPublicKey(t *testing.T) { 16 wrongPublicKeys := [...][ed25519.PublicKeySize]byte{ 17 { // y = p 18 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 19 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 21 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 22 }, 23 { // y > p 24 0xed + 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 28 }, 29 { // x^2 = u/v = (y^2-1)/(dy^2+1) is not a quadratic residue 30 0x9a, 0x0a, 0xbe, 0xc6, 0x23, 0xcb, 0x5a, 0x23, 31 0x4e, 0x49, 0xd8, 0x92, 0xc2, 0x72, 0xd5, 0xa8, 32 0x27, 0xff, 0x42, 0x07, 0x7d, 0xe3, 0xf2, 0xb4, 33 0x74, 0x75, 0x9d, 0x04, 0x34, 0xed, 0xa6, 0x70, 34 }, 35 { // y = 1 and x^2 = u/v = 0, and the sign of X is 1 36 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 0x80, 40 }, 41 { // y = -1 and x^2 = u/v = 0, and the sign of X is 1 42 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f | 0x80, 46 }, 47 } 48 sig := (&[ed25519.SignatureSize]byte{})[:] 49 for _, public := range wrongPublicKeys { 50 got := ed25519.Verify(public[:], []byte(""), sig) 51 want := false 52 if got != want { 53 test.ReportError(t, got, want, public) 54 } 55 } 56 } 57 58 func TestSigner(t *testing.T) { 59 seed := (&[ed25519.SeedSize]byte{})[:] 60 _, _ = rand.Read(seed) 61 key := ed25519.NewKeyFromSeed(seed) 62 63 priv := key.Seed() 64 if !bytes.Equal(seed, priv) { 65 got := priv 66 want := seed 67 test.ReportError(t, got, want) 68 } 69 70 for _, o := range []ed25519.SignerOptions{ 71 {Scheme: ed25519.ED25519, Hash: crypto.Hash(0), Context: ""}, 72 {Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: ""}, 73 {Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: "non-empty"}, 74 {Scheme: ed25519.ED25519Ctx, Hash: crypto.Hash(0), Context: "non-empty"}, 75 } { 76 testSigner(t, key, o) 77 } 78 } 79 80 func testSigner(t *testing.T, signer crypto.Signer, ops ed25519.SignerOptions) { 81 msg := make([]byte, 64) 82 _, _ = rand.Read(msg) 83 84 sig, err := signer.Sign(nil, msg, ops) 85 if err != nil { 86 got := err 87 var want error 88 test.ReportError(t, got, want, ops) 89 } 90 91 if len(sig) != ed25519.SignatureSize { 92 got := len(sig) 93 want := ed25519.SignatureSize 94 test.ReportError(t, got, want, ops) 95 } 96 97 pubSigner, ok := signer.Public().(ed25519.PublicKey) 98 if !ok { 99 got := ok 100 want := true 101 test.ReportError(t, got, want, ops) 102 } 103 104 got := ed25519.VerifyAny(pubSigner, msg, sig, ops) 105 want := true 106 if got != want { 107 test.ReportError(t, got, want, ops) 108 } 109 } 110 111 type badReader struct{} 112 113 func (badReader) Read([]byte) (int, error) { return 0, errors.New("cannot read") } 114 115 func TestErrors(t *testing.T) { 116 t.Run("badHash", func(t *testing.T) { 117 var msg [16]byte 118 ops := crypto.SHA224 119 _, priv, _ := ed25519.GenerateKey(nil) 120 _, got := priv.Sign(nil, msg[:], ops) 121 want := errors.New("ed25519: bad hash algorithm") 122 if got.Error() != want.Error() { 123 test.ReportError(t, got, want) 124 } 125 }) 126 t.Run("badReader", func(t *testing.T) { 127 _, _, got := ed25519.GenerateKey(badReader{}) 128 want := errors.New("cannot read") 129 if got.Error() != want.Error() { 130 test.ReportError(t, got, want) 131 } 132 }) 133 t.Run("wrongSeedSize", func(t *testing.T) { 134 var seed [256]byte 135 var want error 136 got := test.CheckPanic(func() { ed25519.NewKeyFromSeed(seed[:]) }) 137 if got != want { 138 test.ReportError(t, got, want) 139 } 140 }) 141 } 142 143 func BenchmarkEd25519Ph(b *testing.B) { 144 msg := make([]byte, 128) 145 _, _ = rand.Read(msg) 146 147 b.Run("Sign", func(b *testing.B) { 148 _, key, _ := ed25519.GenerateKey(rand.Reader) 149 ctx := "" 150 b.ResetTimer() 151 for i := 0; i < b.N; i++ { 152 _ = ed25519.SignPh(key, msg, ctx) 153 } 154 }) 155 b.Run("Verify", func(b *testing.B) { 156 pub, priv, _ := ed25519.GenerateKey(rand.Reader) 157 ctx := "" 158 sig := ed25519.SignPh(priv, msg, ctx) 159 b.ResetTimer() 160 for i := 0; i < b.N; i++ { 161 ed25519.VerifyPh(pub, msg, sig, ctx) 162 } 163 }) 164 } 165 166 func BenchmarkEd25519Ctx(b *testing.B) { 167 ctx := "a context" 168 msg := make([]byte, 128) 169 _, _ = rand.Read(msg) 170 b.Run("Sign", func(b *testing.B) { 171 _, priv, _ := ed25519.GenerateKey(rand.Reader) 172 b.ResetTimer() 173 for i := 0; i < b.N; i++ { 174 _ = ed25519.SignWithCtx(priv, msg, ctx) 175 } 176 }) 177 b.Run("Verify", func(b *testing.B) { 178 pub, priv, _ := ed25519.GenerateKey(rand.Reader) 179 sig := ed25519.SignWithCtx(priv, msg, ctx) 180 b.ResetTimer() 181 for i := 0; i < b.N; i++ { 182 ed25519.VerifyWithCtx(pub, msg, sig, ctx) 183 } 184 }) 185 } 186 187 func Example_ed25519() { 188 // import "github.com/cloudflare/circl/sign/ed25519" 189 // import "crypto/rand" 190 191 // Generating Alice's key pair 192 pub, priv, err := ed25519.GenerateKey(rand.Reader) 193 if err != nil { 194 panic("error on generating keys") 195 } 196 197 // Alice signs a message. 198 message := []byte("A message to be signed") 199 signature := ed25519.Sign(priv, message) 200 201 // Anyone can verify the signature using Alice's public key. 202 ok := ed25519.Verify(pub, message, signature) 203 fmt.Println(ok) 204 // Output: true 205 } 206 207 func ExampleSignPh() { 208 // import "github.com/cloudflare/circl/sign/ed25519" 209 // import "crypto/rand" 210 211 // Generating Alice's key pair 212 pub, priv, err := ed25519.GenerateKey(rand.Reader) 213 if err != nil { 214 panic("error on generating keys") 215 } 216 217 // Alice signs a message. 218 message := []byte("A message to be signed") 219 ctx := "an optional context string" 220 221 signature := ed25519.SignPh(priv, message, ctx) 222 223 // Anyone can verify the signature using Alice's public key. 224 ok := ed25519.VerifyPh(pub, message, signature, ctx) 225 fmt.Println(ok) 226 // Output: true 227 } 228 229 func ExampleSignWithCtx() { 230 // import "github.com/cloudflare/circl/sign/ed25519" 231 // import "crypto/rand" 232 233 // Generating Alice's key pair 234 pub, priv, err := ed25519.GenerateKey(rand.Reader) 235 if err != nil { 236 panic("error on generating keys") 237 } 238 239 // Alice signs a message. 240 message := []byte("A message to be signed") 241 ctx := "a non-empty context string" 242 243 signature := ed25519.SignWithCtx(priv, message, ctx) 244 245 // Anyone can verify the signature using Alice's public key. 246 ok := ed25519.VerifyWithCtx(pub, message, signature, ctx) 247 fmt.Println(ok) 248 // Output: true 249 }