ed25519: turn into a wrapper for crypto/ed25519 beginning with Go 1.13
Updates golang/go#25355
Change-Id: Id077d96749194943914d956bd8e79e5272477d7e
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/182698
Reviewed-by: Russ Cox <rsc@golang.org>
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 @@
"strings"
"testing"
+ "golang.org/x/crypto/ed25519"
"golang.org/x/crypto/ed25519/internal/edwards25519"
)
@@ -28,7 +29,7 @@
}
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 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 @@
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 @@
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 @@
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 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 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")
+ }
+}