diff --git a/ed25519/ed25519.go b/ed25519/ed25519.go index d6f683b..c7f8c7e 100644 --- a/ed25519/ed25519.go +++ b/ed25519/ed25519.go @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// In Go 1.13, the ed25519 package was promoted to the standard library as +// crypto/ed25519, and this package became a wrapper for the standard library one. +// +// +build !go1.13 + // Package ed25519 implements the Ed25519 signature algorithm. See // https://ed25519.cr.yp.to/. // diff --git a/ed25519/ed25519_go113.go b/ed25519/ed25519_go113.go new file mode 100644 index 0000000..d1448d8 --- /dev/null +++ b/ed25519/ed25519_go113.go @@ -0,0 +1,73 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.13 + +// Package ed25519 implements the Ed25519 signature algorithm. See +// https://ed25519.cr.yp.to/. +// +// These functions are also compatible with the “Ed25519” function defined in +// RFC 8032. However, unlike RFC 8032's formulation, this package's private key +// representation includes a public key suffix to make multiple signing +// operations with the same key more efficient. This package refers to the RFC +// 8032 private key as the “seed”. +// +// Beginning with Go 1.13, the functionality of this package was moved to the +// standard library as crypto/ed25519. This package only acts as a compatibility +// wrapper. +package ed25519 + +import ( + "crypto/ed25519" + "io" +) + +const ( + // PublicKeySize is the size, in bytes, of public keys as used in this package. + PublicKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // SignatureSize is the size, in bytes, of signatures generated and verified by this package. + SignatureSize = 64 + // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032. + SeedSize = 32 +) + +// PublicKey is the type of Ed25519 public keys. +// +// This type is an alias for crypto/ed25519's PublicKey type. +// See the crypto/ed25519 package for the methods on this type. +type PublicKey = ed25519.PublicKey + +// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. +// +// This type is an alias for crypto/ed25519's PrivateKey type. +// See the crypto/ed25519 package for the methods on this type. +type PrivateKey = ed25519.PrivateKey + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + return ed25519.GenerateKey(rand) +} + +// NewKeyFromSeed calculates a private key from a seed. It will panic if +// len(seed) is not SeedSize. This function is provided for interoperability +// with RFC 8032. RFC 8032's private keys correspond to seeds in this +// package. +func NewKeyFromSeed(seed []byte) PrivateKey { + return ed25519.NewKeyFromSeed(seed) +} + +// Sign signs the message with privateKey and returns a signature. It will +// panic if len(privateKey) is not PrivateKeySize. +func Sign(privateKey PrivateKey, message []byte) []byte { + return ed25519.Sign(privateKey, message) +} + +// Verify reports whether sig is a valid signature of message by publicKey. It +// will panic if len(publicKey) is not PublicKeySize. +func Verify(publicKey PublicKey, message, sig []byte) bool { + return ed25519.Verify(publicKey, message, sig) +} diff --git a/ed25519/ed25519_test.go b/ed25519/ed25519_test.go index 8094603..13187cd 100644 --- a/ed25519/ed25519_test.go +++ b/ed25519/ed25519_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package ed25519 +package ed25519_test import ( "bufio" @@ -15,6 +15,7 @@ import ( "strings" "testing" + "golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519/internal/edwards25519" ) @@ -28,7 +29,7 @@ func (zeroReader) Read(buf []byte) (int, error) { } func TestUnmarshalMarshal(t *testing.T) { - pub, _, _ := GenerateKey(rand.Reader) + pub, _, _ := ed25519.GenerateKey(rand.Reader) var A edwards25519.ExtendedGroupElement var pubBytes [32]byte @@ -47,28 +48,28 @@ func TestUnmarshalMarshal(t *testing.T) { func TestSignVerify(t *testing.T) { var zero zeroReader - public, private, _ := GenerateKey(zero) + public, private, _ := ed25519.GenerateKey(zero) message := []byte("test message") - sig := Sign(private, message) - if !Verify(public, message, sig) { + sig := ed25519.Sign(private, message) + if !ed25519.Verify(public, message, sig) { t.Errorf("valid signature rejected") } wrongMessage := []byte("wrong message") - if Verify(public, wrongMessage, sig) { + if ed25519.Verify(public, wrongMessage, sig) { t.Errorf("signature of different message accepted") } } func TestCryptoSigner(t *testing.T) { var zero zeroReader - public, private, _ := GenerateKey(zero) + public, private, _ := ed25519.GenerateKey(zero) signer := crypto.Signer(private) publicInterface := signer.Public() - public2, ok := publicInterface.(PublicKey) + public2, ok := publicInterface.(ed25519.PublicKey) if !ok { t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) } @@ -84,7 +85,7 @@ func TestCryptoSigner(t *testing.T) { t.Fatalf("error from Sign(): %s", err) } - if !Verify(public, message, signature) { + if !ed25519.Verify(public, message, signature) { t.Errorf("Verify failed on signature from Sign()") } } @@ -121,31 +122,31 @@ func TestGolden(t *testing.T) { sig, _ := hex.DecodeString(parts[3]) // The signatures in the test vectors also include the message // at the end, but we just want R and S. - sig = sig[:SignatureSize] + sig = sig[:ed25519.SignatureSize] - if l := len(pubKey); l != PublicKeySize { + if l := len(pubKey); l != ed25519.PublicKeySize { t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) } - var priv [PrivateKeySize]byte + var priv [ed25519.PrivateKeySize]byte copy(priv[:], privBytes) copy(priv[32:], pubKey) - sig2 := Sign(priv[:], msg) + sig2 := ed25519.Sign(priv[:], msg) if !bytes.Equal(sig, sig2[:]) { t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) } - if !Verify(pubKey, msg, sig2) { + if !ed25519.Verify(pubKey, msg, sig2) { t.Errorf("signature failed to verify on line %d", lineNo) } - priv2 := NewKeyFromSeed(priv[:32]) + priv2 := ed25519.NewKeyFromSeed(priv[:32]) if !bytes.Equal(priv[:], priv2) { t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2) } - if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) { + if pubKey2 := priv2.Public().(ed25519.PublicKey); !bytes.Equal(pubKey, pubKey2) { t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2) } @@ -178,7 +179,7 @@ func TestMalleability(t *testing.T) { 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, } - if Verify(publicKey, msg, sig) { + if ed25519.Verify(publicKey, msg, sig) { t.Fatal("non-canonical signature accepted") } } @@ -186,7 +187,7 @@ func TestMalleability(t *testing.T) { func BenchmarkKeyGeneration(b *testing.B) { var zero zeroReader for i := 0; i < b.N; i++ { - if _, _, err := GenerateKey(zero); err != nil { + if _, _, err := ed25519.GenerateKey(zero); err != nil { b.Fatal(err) } } @@ -194,27 +195,27 @@ func BenchmarkKeyGeneration(b *testing.B) { func BenchmarkSigning(b *testing.B) { var zero zeroReader - _, priv, err := GenerateKey(zero) + _, priv, err := ed25519.GenerateKey(zero) if err != nil { b.Fatal(err) } message := []byte("Hello, world!") b.ResetTimer() for i := 0; i < b.N; i++ { - Sign(priv, message) + ed25519.Sign(priv, message) } } func BenchmarkVerification(b *testing.B) { var zero zeroReader - pub, priv, err := GenerateKey(zero) + pub, priv, err := ed25519.GenerateKey(zero) if err != nil { b.Fatal(err) } message := []byte("Hello, world!") - signature := Sign(priv, message) + signature := ed25519.Sign(priv, message) b.ResetTimer() for i := 0; i < b.N; i++ { - Verify(pub, message, signature) + ed25519.Verify(pub, message, signature) } } diff --git a/ed25519/go113_test.go b/ed25519/go113_test.go new file mode 100644 index 0000000..76edde0 --- /dev/null +++ b/ed25519/go113_test.go @@ -0,0 +1,24 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.13 + +package ed25519_test + +import ( + ed25519std "crypto/ed25519" + "golang.org/x/crypto/ed25519" + "testing" +) + +func TestTypeAlias(t *testing.T) { + var zero zeroReader + public, private, _ := ed25519std.GenerateKey(zero) + + message := []byte("test message") + sig := ed25519.Sign(private, message) + if !ed25519.Verify(public, message, sig) { + t.Errorf("valid signature rejected") + } +}