mirror of https://github.com/golang/go.git
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>
This commit is contained in:
parent
f375b305c8
commit
02ed0e5e67
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue