]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/ed25519: improve Ed25519ctx docs and add example
authorFilippo Valsorda <filippo@golang.org>
Thu, 29 Dec 2022 12:08:48 +0000 (13:08 +0100)
committerGopher Robot <gobot@golang.org>
Tue, 17 Jan 2023 16:25:39 +0000 (16:25 +0000)
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>

src/crypto/ed25519/ed25519.go
src/crypto/ed25519/ed25519_test.go

index 921bbaa8edd14ff581290ab17c644f7dda05e32f..a45d056851257cacd5c43bdcbc7754c5b38fdc41 100644 (file)
@@ -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 {
index ae5c872e02fc66189ec6fb753d1d224edf5ffa52..47c8698e2a5945b91cf3b83ec84ab324a7cbf8d4 100644 (file)
@@ -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) {