// Copyright 2016 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.

// 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”.
package ed25519 // This code is a port of the public domain, “ref10” implementation of ed25519 // from SUPERCOP. import ( cryptorand ) 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. type PublicKey []byte // Any methods implemented on PublicKey might need to also be implemented on // PrivateKey, as the latter embeds the former and will expose its methods. // Equal reports whether pub and x have the same value. func ( PublicKey) ( crypto.PublicKey) bool { , := .(PublicKey) if ! { return false } return bytes.Equal(, ) } // PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. type PrivateKey []byte // Public returns the PublicKey corresponding to priv. func ( PrivateKey) () crypto.PublicKey { := make([]byte, PublicKeySize) copy(, [32:]) return PublicKey() } // Equal reports whether priv and x have the same value. func ( PrivateKey) ( crypto.PrivateKey) bool { , := .(PrivateKey) if ! { return false } return bytes.Equal(, ) } // Seed returns the private key seed corresponding to priv. It is provided for // interoperability with RFC 8032. RFC 8032's private keys correspond to seeds // in this package. func ( PrivateKey) () []byte { := make([]byte, SeedSize) copy(, [:32]) return } // Sign signs the given message with priv. // Ed25519 performs two passes over messages to be signed and therefore cannot // handle pre-hashed messages. Thus opts.HashFunc() must return zero to // indicate the message hasn't been hashed. This can be achieved by passing // crypto.Hash(0) as the value for opts. func ( PrivateKey) ( io.Reader, []byte, crypto.SignerOpts) ( []byte, error) { if .HashFunc() != crypto.Hash(0) { return nil, errors.New("ed25519: cannot sign hashed message") } return Sign(, ), nil } // GenerateKey generates a public/private key pair using entropy from rand. // If rand is nil, crypto/rand.Reader will be used. func ( io.Reader) (PublicKey, PrivateKey, error) { if == nil { = cryptorand.Reader } := make([]byte, SeedSize) if , := io.ReadFull(, ); != nil { return nil, nil, } := NewKeyFromSeed() := make([]byte, PublicKeySize) copy(, [32:]) return , , nil } // 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 ( []byte) PrivateKey { // Outline the function body so that the returned key can be stack-allocated. := make([]byte, PrivateKeySize) newKeyFromSeed(, ) return } func (, []byte) { if := len(); != SeedSize { panic("ed25519: bad seed length: " + strconv.Itoa()) } := sha512.Sum512() [0] &= 248 [31] &= 127 [31] |= 64 var edwards25519.ExtendedGroupElement var [32]byte copy([:], [:]) edwards25519.GeScalarMultBase(&, &) var [32]byte .ToBytes(&) copy(, ) copy([32:], [:]) } // Sign signs the message with privateKey and returns a signature. It will // panic if len(privateKey) is not PrivateKeySize. func ( PrivateKey, []byte) []byte { // Outline the function body so that the returned signature can be // stack-allocated. := make([]byte, SignatureSize) sign(, , ) return } func (, , []byte) { if := len(); != PrivateKeySize { panic("ed25519: bad private key length: " + strconv.Itoa()) } := sha512.New() .Write([:32]) var , , [64]byte var [32]byte .Sum([:0]) copy([:], [:]) [0] &= 248 [31] &= 63 [31] |= 64 .Reset() .Write([32:]) .Write() .Sum([:0]) var [32]byte edwards25519.ScReduce(&, &) var edwards25519.ExtendedGroupElement edwards25519.GeScalarMultBase(&, &) var [32]byte .ToBytes(&) .Reset() .Write([:]) .Write([32:]) .Write() .Sum([:0]) var [32]byte edwards25519.ScReduce(&, &) var [32]byte edwards25519.ScMulAdd(&, &, &, &) copy([:], [:]) copy([32:], [:]) } // Verify reports whether sig is a valid signature of message by publicKey. It // will panic if len(publicKey) is not PublicKeySize. func ( PublicKey, , []byte) bool { if := len(); != PublicKeySize { panic("ed25519: bad public key length: " + strconv.Itoa()) } if len() != SignatureSize || [63]&224 != 0 { return false } var edwards25519.ExtendedGroupElement var [32]byte copy([:], ) if !.FromBytes(&) { return false } edwards25519.FeNeg(&.X, &.X) edwards25519.FeNeg(&.T, &.T) := sha512.New() .Write([:32]) .Write([:]) .Write() var [64]byte .Sum([:0]) var [32]byte edwards25519.ScReduce(&, &) var edwards25519.ProjectiveGroupElement var [32]byte copy([:], [32:]) // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in // the range [0, order) in order to prevent signature malleability. if !edwards25519.ScMinimal(&) { return false } edwards25519.GeDoubleScalarMultVartime(&, &, &, &) var [32]byte .ToBytes(&) return bytes.Equal([:32], [:]) }