summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2022-12-29 13:08:48 +0100
committerGopher Robot <gobot@golang.org>2023-01-17 16:25:39 +0000
commit02ed0e5e67530e6b041989d55048ce373dc60327 (patch)
tree9b457bf20a61115e16355bfa5057e9e697994818
parentf375b305c801515b587719490b4be0db1a66e20c (diff)
downloadgo-git-02ed0e5e67530e6b041989d55048ce373dc60327.tar.gz
crypto/ed25519: improve Ed25519ctx docs and add example
Change-Id: Ic215a90d1e1daa5805dbab1dc56480281e53b341 Reviewed-on: https://go-review.googlesource.com/c/go/+/459975 Auto-Submit: Filippo Valsorda <filippo@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Roland Shoemaker <roland@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
-rw-r--r--src/crypto/ed25519/ed25519.go37
-rw-r--r--src/crypto/ed25519/ed25519_test.go23
2 files changed, 45 insertions, 15 deletions
diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go
index 921bbaa8ed..a45d056851 100644
--- a/src/crypto/ed25519/ed25519.go
+++ b/src/crypto/ed25519/ed25519.go
@@ -49,10 +49,10 @@ func (pub PublicKey) Equal(x crypto.PublicKey) bool {
return bytes.Equal(pub, xx)
}
-// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
+// PrivateKey is the type of Ed25519 private keys. It implements [crypto.Signer].
type PrivateKey []byte
-// Public returns the PublicKey corresponding to priv.
+// Public returns the [PublicKey] corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
publicKey := make([]byte, PublicKeySize)
copy(publicKey, priv[32:])
@@ -75,11 +75,15 @@ func (priv PrivateKey) Seed() []byte {
return bytes.Clone(priv[:SeedSize])
}
-// Sign signs the given message with priv. rand is ignored. If opts.HashFunc()
-// is crypto.SHA512, the pre-hashed variant Ed25519ph is used and message is
-// expected to be a SHA-512 hash, otherwise opts.HashFunc() must be
-// crypto.Hash(0) and the message must not be hashed, as Ed25519 performs two
+// Sign signs the given message with priv. rand is ignored.
+//
+// If opts.HashFunc() is [crypto.SHA512], the pre-hashed variant Ed25519ph is used
+// and message is expected to be a SHA-512 hash, otherwise opts.HashFunc() must
+// be [crypto.Hash](0) and the message must not be hashed, as Ed25519 performs two
// passes over messages to be signed.
+//
+// A value of type [Options] can be used as opts, or crypto.Hash(0) or
+// crypto.SHA512 directly to select plain Ed25519 or Ed25519ph, respectively.
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
hash := opts.HashFunc()
context := ""
@@ -108,7 +112,7 @@ func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOp
}
}
-// Options can be used with PrivateKey.Sign or VerifyWithOptions
+// Options can be used with [PrivateKey.Sign] or [VerifyWithOptions]
// to select Ed25519 variants.
type Options struct {
// Hash can be zero for regular Ed25519, or crypto.SHA512 for Ed25519ph.
@@ -119,10 +123,11 @@ type Options struct {
Context string
}
+// HashFunc returns o.Hash.
func (o *Options) HashFunc() crypto.Hash { return o.Hash }
// GenerateKey generates a public/private key pair using entropy from rand.
-// If rand is nil, crypto/rand.Reader will be used.
+// If rand is nil, [crypto/rand.Reader] will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptorand.Reader
@@ -141,7 +146,7 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
-// len(seed) is not SeedSize. This function is provided for interoperability
+// 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 {
@@ -170,7 +175,7 @@ func newKeyFromSeed(privateKey, seed []byte) {
}
// Sign signs the message with privateKey and returns a signature. It will
-// panic if len(privateKey) is not PrivateKeySize.
+// panic if len(privateKey) is not [PrivateKeySize].
func Sign(privateKey PrivateKey, message []byte) []byte {
// Outline the function body so that the returned signature can be
// stack-allocated.
@@ -245,16 +250,18 @@ func sign(signature, privateKey, message []byte, domPrefix, context string) {
}
// Verify reports whether sig is a valid signature of message by publicKey. It
-// will panic if len(publicKey) is not PublicKeySize.
+// will panic if len(publicKey) is not [PublicKeySize].
func Verify(publicKey PublicKey, message, sig []byte) bool {
return verify(publicKey, message, sig, domPrefixPure, "")
}
// VerifyWithOptions reports whether sig is a valid signature of message by
-// publicKey. A valid signature is indicated by returning a nil error.
-// If opts.Hash is crypto.SHA512, the pre-hashed variant Ed25519ph is used
-// and message is expected to be a SHA-512 hash, otherwise opts.Hash must
-// be crypto.Hash(0) and the message must not be hashed, as Ed25519 performs two
+// publicKey. A valid signature is indicated by returning a nil error. It will
+// panic if len(publicKey) is not [PublicKeySize].
+//
+// If opts.Hash is [crypto.SHA512], the pre-hashed variant Ed25519ph is used and
+// message is expected to be a SHA-512 hash, otherwise opts.Hash must be
+// [crypto.Hash](0) and the message must not be hashed, as Ed25519 performs two
// passes over messages to be signed.
func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) error {
switch {
diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go
index ae5c872e02..47c8698e2a 100644
--- a/src/crypto/ed25519/ed25519_test.go
+++ b/src/crypto/ed25519/ed25519_test.go
@@ -14,11 +14,34 @@ import (
"crypto/sha512"
"encoding/hex"
"internal/testenv"
+ "log"
"os"
"strings"
"testing"
)
+func Example_ed25519ctx() {
+ pub, priv, err := GenerateKey(nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ msg := []byte("The quick brown fox jumps over the lazy dog")
+
+ sig, err := priv.Sign(nil, msg, &Options{
+ Context: "Example_ed25519ctx",
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := VerifyWithOptions(pub, msg, sig, &Options{
+ Context: "Example_ed25519ctx",
+ }); err != nil {
+ log.Fatal("invalid signature")
+ }
+}
+
type zeroReader struct{}
func (zeroReader) Read(buf []byte) (int, error) {