ed25519

package
v0.0.0-...-1f23a7b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2023 License: BSD-3-Clause Imports: 12 Imported by: 66

Documentation

Overview

Package ed25519 implements the Ed25519 signature algorithm. See https://ed25519.cr.yp.to/.

These functions are mostly 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”.

The default verification behavior is neither identical to that of the Go standard library, nor that as specified in FIPS 186-5. If exact compatibility with either definition is required, use the appropriate VerifyOptions presets.

Example

Example demonstrates common operations.

// Basic operations are API compatible with crypto/ed25519, as in
// curve25519-voi implements a superset of the crypto/ed25519 API.

msg := []byte("test message")

// Key generation
publicKey, privateKey, err := GenerateKey(rand.Reader)
if err != nil {
	panic("GenerateKey: " + err.Error())
}

// Signing
sig := Sign(privateKey, msg)

// Verification
if !Verify(publicKey, msg, sig) {
	panic("Verify: failed")
}

// Verification semantics are incompatible with crypto/ed25519
// by default.  It is possible to generate signatures that will be
// accepted by one (and rejected by the other), though this will
// NEVER happen during normal operation.
//
// If exact compatibility with the standard library is required
// then VerifyWithOptions must be used with the appropriate options.
//
// Note: Over 99% of the users do not need this, the various edge
// case incompatiblities are systemic across the whole Ed25519
// ecosystem as a whole, and RFC 8032 explicitly allows for this
// situation.
opts := &Options{
	Verify: VerifyOptionsStdLib,
}
if !VerifyWithOptions(publicKey, msg, sig, opts) {
	panic("VerifyWithOptions: failed")
}

// curve25519-voi supports Ed25519ph and Ed25519ctx as defined in
// RFC 8032 in addition to Ed25519pure.

// Ed25519ctx
//
// Note: Due to Context being defined as a string, a 0-length
// context is not supported, even though it is allowed but
// discouraged by the RFC.
opts = &Options{
	Context: string("test context"),
}
sig, err = privateKey.Sign(nil, msg, opts)
if err != nil {
	panic("SignWithOptions(ctx): " + err.Error())
}

if !VerifyWithOptions(publicKey, msg, sig, opts) {
	panic("VerifyWithOptions(ctx): failed")
}

// Ed25519ph
prehash := sha512.Sum512(msg)
opts = &Options{
	Hash: crypto.SHA512,
}
if sig, err = privateKey.Sign(nil, prehash[:], opts); err != nil {
	panic("SignWithOptions(ph): " + err.Error())
}
if !VerifyWithOptions(publicKey, prehash[:], sig, opts) {
	panic("VerifyWithOptions(ph): failed")
}

fmt.Println("ok")
Output:

ok

Index

Examples

Constants

View Source
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

	// ContextMaxSize is the maximum allowed context length for Ed25519ctx.
	ContextMaxSize = 255
)

Variables

View Source
var (
	// VerifyOptionsDefault specifies verification behavior that is
	// used by this package by default.
	VerifyOptionsDefault = &VerifyOptions{
		AllowSmallOrderR: true,
	}

	// VerifyOptionsStdLib specifies verification behavior that is
	// compatible with that provided by the Go `crypto/ed25519` package.
	//
	// Note: This preset is incompatible with batch verification.
	VerifyOptionsStdLib = &VerifyOptions{
		AllowSmallOrderA:   true,
		AllowSmallOrderR:   true,
		AllowNonCanonicalA: true,
		CofactorlessVerify: true,
	}

	// VerifyOptionsFIPS_186_5 specifies verification behavior that is
	// compatible with FIPS 186-5.  The behavior provided by this preset
	// also matches RFC 8032 (with cofactored verification).
	VerifyOptionsFIPS_186_5 = &VerifyOptions{
		AllowSmallOrderA: true,
		AllowSmallOrderR: true,
	}

	// VerifyOptionsZIP_215 specifies verification behavior that is
	// compatible with ZIP-215.
	VerifyOptionsZIP_215 = &VerifyOptions{
		AllowSmallOrderA:   true,
		AllowSmallOrderR:   true,
		AllowNonCanonicalA: true,
		AllowNonCanonicalR: true,
	}
)

Functions

func GenerateKey

func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error)

GenerateKey generates a public/private key pair using entropy from rand. If rand is nil, crypto/rand.Reader will be used.

func Sign

func Sign(privateKey PrivateKey, message []byte) []byte

Sign signs the message with privateKey and returns a signature. It will panic if len(privateKey) is not PrivateKeySize.

func Verify

func Verify(publicKey PublicKey, message, sig []byte) bool

Verify reports whether sig is a valid signature of message by publicKey. It will panic if len(publicKey) is not PublicKeySize.

func VerifyExpanded

func VerifyExpanded(publicKey *ExpandedPublicKey, message, sig []byte) bool

VerifyExpanded reports whether sig is a valid Ed25519 signature by publicKey.

func VerifyExpandedWithOptions

func VerifyExpandedWithOptions(publicKey *ExpandedPublicKey, message, sig []byte, opts *Options) bool

VerifyExpandedWithOptions reports whether sig is a valid Ed25519 signature by publicKey with the extra Options to support Ed25519ph (pre-hashed by SHA-512) or Ed25519ctx (includes a domain separation context). It will panic if len(message) is not sha512.Size (if pre-hashed), len(opts.Context) is greater than ContextMaxSize, or opts is nil.

func VerifyWithOptions

func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) bool

VerifyWithOptions reports whether sig is a valid Ed25519 signature by publicKey with the extra Options to support Ed25519ph (pre-hashed by SHA-512) or Ed25519ctx (includes a domain separation context). It will panic if len(publicKey) is not PublicKeySize, len(message) is not sha512.Size (if pre-hashed), len(opts.Context) is greater than ContextMaxSize, or opts is nil.

Types

type BatchVerifier

type BatchVerifier struct {
	// contains filtered or unexported fields
}

BatchVerifier accumulates batch entries with Add, before performing batch verification with Verify.

Example

ExampleBatchVerifier demonstrates batch verification functionality.

// curve25519-voi provides batch verification, with an API that
// is similar to ed25519consensus.

msg1 := []byte("test message")
msg2 := []byte("test message 2")
msg3 := []byte("test message with a vengance")
msg4 := []byte("live free or test message")
msg5 := []byte("a good day to test message")

publicKey, privateKey, err := GenerateKey(rand.Reader)
if err != nil {
	panic("GenerateKey: " + err.Error())
}

publicKey2, privateKey2, err := GenerateKey(rand.Reader)
if err != nil {
	panic("GenerateKey: " + err.Error())
}

sig1 := Sign(privateKey, msg1)
sig2 := Sign(privateKey2, msg2)
sig3 := Sign(privateKey, msg3)
opts := &Options{
	Context: "yippie ki-yay",
	Verify:  VerifyOptionsFIPS_186_5,
}
sig4, err := privateKey.Sign(nil, msg4, opts)
if err != nil {
	panic("SignWithOptions: " + err.Error())
}
sig5 := Sign(privateKey, msg5)

// Batch verification
verifier := NewBatchVerifier()
verifier.Add(publicKey, msg1, sig1)
verifier.Add(publicKey2, msg2, sig2) // Public keys can be different.
verifier.Add(publicKey, msg3, sig3)

// It is possible to specify verification options on a
// per-batch-entry basis, including Ed25519ph/Ed25519ctx.
verifier.AddWithOptions(publicKey, msg4, sig4, opts)

// Only verify the batch, receiving no information about which
// batch entries are incorrect in the event of a failure.
//
// Note: Verify is probably more useful.
if !verifier.VerifyBatchOnly(rand.Reader) {
	panic("verifier.VerifyBatchOnly failed")
}

// Verify the batch, and return a vector showing the valid entries.
allOk, okVec := verifier.Verify(rand.Reader)
if !allOk {
	panic("verifier.Verify failed")
}
for i, v := range okVec {
	if !v {
		panic(fmt.Sprintf("verifier.Verify: entry %d invalid", i))
	}
}

// Batch failure
sig5[16] ^= 0xa5
verifier.Add(publicKey, msg5, sig5)
allOk, okVec = verifier.Verify(rand.Reader)
if allOk {
	panic("verifier.Verify succeeded when batch should fail")
}
for i, v := range okVec[:4] {
	if !v {
		panic(fmt.Sprintf("verifier.Verify: entry %d invalid", i))
	}
}
if okVec[4] {
	panic("verifier.Verify: entry 4 valid")
}

fmt.Println("ok")
Output:

ok

func NewBatchVerifier

func NewBatchVerifier() *BatchVerifier

NewBatchVerfier creates an empty BatchVerifier.

func NewBatchVerifierWithCapacity

func NewBatchVerifierWithCapacity(n int) *BatchVerifier

NewBatchVerifierWithCapacity creates an empty BatchVerifier, with preallocations for a pre-determined batch size hint.

func (*BatchVerifier) Add

func (v *BatchVerifier) Add(publicKey PublicKey, message, sig []byte)

Add adds a (public key, message, sig) triple to the current batch.

func (*BatchVerifier) AddExpanded

func (v *BatchVerifier) AddExpanded(publicKey *ExpandedPublicKey, message, sig []byte)

AddExpanded adds a (expanded public key, message, sig) triple to the current batch.

func (*BatchVerifier) AddExpandedWithOptions

func (v *BatchVerifier) AddExpandedWithOptions(publicKey *ExpandedPublicKey, message, sig []byte, opts *Options)

AddExpandedWithOptions adds a (precomputed public key, message, sig, opts) quad to the current batch.

WARNING: This routine will panic if opts is nil.

func (*BatchVerifier) AddWithOptions

func (v *BatchVerifier) AddWithOptions(publicKey PublicKey, message, sig []byte, opts *Options)

AddWithOptions adds a (public key, message, sig, opts) quad to the current batch.

WARNING: This routine will panic if opts is nil.

func (*BatchVerifier) ForceNoPublicKeyExpansion

func (v *BatchVerifier) ForceNoPublicKeyExpansion() *BatchVerifier

ForceNoPublicKeyExpansion disables the key expansion for a given batch. This setting will NOT persist across Reset, and must be called again if a batch is reused.

This setting can be used for large batches that are built via Add/AddWithOptions to reduce memory consumption and allocations.

func (*BatchVerifier) Reset

func (v *BatchVerifier) Reset() *BatchVerifier

Reset resets a batch for reuse.

Note: This method will reuse the internal entires slice to reduce memory reallocations. If the next batch is known to be significantly smaller it may be more memory efficient to simply create a new batch.

func (*BatchVerifier) Verify

func (v *BatchVerifier) Verify(rand io.Reader) (bool, []bool)

Verify checks all entries in the current batch using entropy from rand, returning true if all entries in the current bach are valid. If one or more signature is invalid, each entry in the batch will be verified serially, and the returned bit-vector will provide information about each individual entry. If rand is nil, crypto/rand.Reader will be used.

Note: This method is only faster than individually verifying each signature if every signature is valid. That said, this method will always out-perform calling VerifyBatchOnly followed by falling back to serial verification.

func (*BatchVerifier) VerifyBatchOnly

func (v *BatchVerifier) VerifyBatchOnly(rand io.Reader) bool

VerifyBatchOnly checks all entries in the current batch using entropy from rand, returning true if all entries are valid and false if any one entry is invalid. If rand is nil, crypto/rand.Reader will be used.

If a failure arises it is unknown which entry failed, the caller must verify each entry individually.

Calling VerifyBatchOnly on an empty batch, or a batch containing any entries that specify cofactor-less verification will return false.

type ExpandedPublicKey

type ExpandedPublicKey struct {
	// contains filtered or unexported fields
}

ExpandedPublicKey is a PublicKey stored in an expanded representation for the purpose of accelerating repeated signature verification.

Precomputation will be faster if more than 1 verification will be done, and each ExpandedPublicKey is ~1.47 KiB in size.

func NewExpandedPublicKey

func NewExpandedPublicKey(publicKey PublicKey) (*ExpandedPublicKey, error)

NewExpandedPublicKey creates a new expanded public key from an existing public key.

func (*ExpandedPublicKey) CompressedY

func (k *ExpandedPublicKey) CompressedY() curve.CompressedEdwardsY

CompressedY returns the unexpanded public key as a compressed Edwards y-coordinate.

type Options

type Options struct {
	// Hash can be crypto.Hash(0) for Ed25519/Ed25519ctx, or crypto.SHA512
	// for Ed25519ph.
	Hash crypto.Hash

	// Context is an optional domain separation context for Ed25519ph and
	// Ed25519ctx. It must be less than or equal to ContextMaxSize
	// in length.
	//
	// Warning: If Hash is crypto.Hash(0) and Context is a zero length
	// string, plain Ed25519 will be used instead of Ed25519ctx.
	Context string

	// AddedRandomness includes additional randomness when signing to
	// attempt to mitigate certain fault injection and side-channel
	// attacks.
	//
	// Warning: If this is set, signatures will be non-deterministic.
	AddedRandomness bool

	// SelfVerify will cause the signing process to verify the signature
	// after signing, to improve resilience against certain fault attacks.
	//
	// Warning: If this is set, signing will be significantly more
	// expensive.
	SelfVerify bool

	// Verify allows specifying verification behavior for compatibility
	// with other Ed25519 implementations.  If left unspecified, the
	// VerifyOptionsDefault will be used, which should be acceptable
	// for most use cases.
	Verify *VerifyOptions
}

Options can be used with PrivateKey.Sign or VerifyWithOptions to select Ed25519 variants.

Example

ExampleOptions demonstrates the configurable verification behavior.

// As alluded to in the basic example, there are currently many
// definitions of Ed25519 signature verification in the wild.
//
// To navigate this, curve25519-voi provides a "sensible" default,
// and also supporting verification behavior that exactly matches
// other common implementations (within reason).

msg := []byte("test message")

publicKey, privateKey, err := GenerateKey(rand.Reader)
if err != nil {
	panic("GenerateKey: " + err.Error())
}
sig := Sign(privateKey, msg)

// FIPS 186-5 (aka RFC 8032 with cofactored verification)
opts := &Options{
	Verify: VerifyOptionsFIPS_186_5,
}
if !VerifyWithOptions(publicKey, msg, sig, opts) {
	panic("VerifyWithOptions(FIPS_186_5): failed")
}

// ZIP-215 (aka ed25519consensus)
opts = &Options{
	Verify: VerifyOptionsZIP_215,
}
opts.Verify = VerifyOptionsZIP_215
if !VerifyWithOptions(publicKey, msg, sig, opts) {
	panic("VerifyWithOptions(default): failed")
}

// Go standard library (crypto/ed25519)
opts.Verify = VerifyOptionsStdLib
if !VerifyWithOptions(publicKey, msg, sig, opts) {
	panic("VerifyWithOptions(StdLib): failed")
}

fmt.Println("ok")
Output:

ok

func (*Options) HashFunc

func (opt *Options) HashFunc() crypto.Hash

HashFunc returns an identifier for the hash function used to produce the message pased to Signer.Sign. For the Ed25519 family this must be crypto.Hash(0) for Ed25519/Ed25519ctx, or crypto.SHA512 for Ed25519ph.

type PrivateKey

type PrivateKey []byte

PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.

func NewKeyFromSeed

func NewKeyFromSeed(seed []byte) PrivateKey

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 (PrivateKey) Equal

func (priv PrivateKey) Equal(x crypto.PrivateKey) bool

Equal reports whether priv and x have the same value. This function will execute in constant time.

func (PrivateKey) Public

func (priv PrivateKey) Public() crypto.PublicKey

Public returns the PublicKey corresponding to priv.

func (PrivateKey) Seed

func (priv PrivateKey) Seed() []byte

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) Sign

func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error)

Sign signs the given message with priv. 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.

If opts.AddRandomness is set, additional entropy from rand will be included. If rand is nil, crypto/rand.Reader will be used.

Warning: This routine will panic if opts is nil.

type PublicKey

type PublicKey []byte

PublicKey is the type of Ed25519 public keys.

func (PublicKey) Equal

func (pub PublicKey) Equal(x crypto.PublicKey) bool

Equal reports whether pub and x have the same value, in variable-time.

type VerifyOptions

type VerifyOptions struct {
	// AllowSmallOrderA allows signatures with a small order A.
	//
	// Note: This disables the check that makes the scheme strongly
	// binding.
	AllowSmallOrderA bool

	// AllowSmallOrder R allows signatures with a small order R.
	//
	// Note: Rejecting small order R is NOT required for binding.
	AllowSmallOrderR bool

	// AllowNonCanonicalA allows signatures with a non-canonical
	// encoding of A.
	AllowNonCanonicalA bool

	// AllowNonCanonicalR allows signatures with a non-canonical
	// encoding of R.
	//
	// Note: Setting this option is incompatible with CofactorlessVerify.
	AllowNonCanonicalR bool

	// CofactorlessVerify uses the cofactorless verification equation,
	// with the final comparison being done as a byte-compare between
	// the signature's R component and the canonical serialization of
	// the equation result (ref10 and derivative behavior).
	//
	// Note: Setting this option is incompatible with batch verification,
	// and is also incompatible with AllowNonCanonicalR.
	CofactorlessVerify bool
}

VerifyOptions can be used to specify verification behavior for compatibility with other Ed25519 implementations.

Directories

Path Synopsis
extra
cache
Package cache implements a set of caching wrappers around Ed25519 signature verification to transparently accelerate repeated verification with the same public key(s).
Package cache implements a set of caching wrappers around Ed25519 signature verification to transparently accelerate repeated verification with the same public key(s).
ecvrf
Package ecvrf implements the "Verifiable Random Functions (VRFs)" IETF draft, providing the ECVRF-EDWARDS25519-SHA512-ELL2 suite.
Package ecvrf implements the "Verifiable Random Functions (VRFs)" IETF draft, providing the ECVRF-EDWARDS25519-SHA512-ELL2 suite.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL