...

Source file src/github.com/lestrrat-go/jwx/x25519/x25519.go

Documentation: github.com/lestrrat-go/jwx/x25519

     1  package x25519
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	cryptorand "crypto/rand"
     7  	"io"
     8  
     9  	"golang.org/x/crypto/curve25519"
    10  
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // This mirrors ed25519's structure for private/public "keys". jwx
    15  // requires dedicated types for these as they drive
    16  // serialization/deserialization logic, as well as encryption types.
    17  //
    18  // Note that with the x25519 scheme, the private key is a sequence of
    19  // 32 bytes, while the public key is the result of X25519(private,
    20  // basepoint).
    21  //
    22  // Portions of this file are from Go's ed25519.go, which is
    23  // Copyright 2016 The Go Authors. All rights reserved.
    24  
    25  const (
    26  	// PublicKeySize is the size, in bytes, of public keys as used in this package.
    27  	PublicKeySize = 32
    28  	// PrivateKeySize is the size, in bytes, of private keys as used in this package.
    29  	PrivateKeySize = 64
    30  	// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
    31  	SeedSize = 32
    32  )
    33  
    34  // PublicKey is the type of X25519 public keys
    35  type PublicKey []byte
    36  
    37  // Any methods implemented on PublicKey might need to also be implemented on
    38  // PrivateKey, as the latter embeds the former and will expose its methods.
    39  
    40  // Equal reports whether pub and x have the same value.
    41  func (pub PublicKey) Equal(x crypto.PublicKey) bool {
    42  	xx, ok := x.(PublicKey)
    43  	if !ok {
    44  		return false
    45  	}
    46  	return bytes.Equal(pub, xx)
    47  }
    48  
    49  // PrivateKey is the type of X25519 private key
    50  type PrivateKey []byte
    51  
    52  // Public returns the PublicKey corresponding to priv.
    53  func (priv PrivateKey) Public() crypto.PublicKey {
    54  	publicKey := make([]byte, PublicKeySize)
    55  	copy(publicKey, priv[SeedSize:])
    56  	return PublicKey(publicKey)
    57  }
    58  
    59  // Equal reports whether priv and x have the same value.
    60  func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
    61  	xx, ok := x.(PrivateKey)
    62  	if !ok {
    63  		return false
    64  	}
    65  	return bytes.Equal(priv, xx)
    66  }
    67  
    68  // Seed returns the private key seed corresponding to priv. It is provided for
    69  // interoperability with RFC 7748. RFC 7748's private keys correspond to seeds
    70  // in this package.
    71  func (priv PrivateKey) Seed() []byte {
    72  	seed := make([]byte, SeedSize)
    73  	copy(seed, priv[:SeedSize])
    74  	return seed
    75  }
    76  
    77  // NewKeyFromSeed calculates a private key from a seed. It will return
    78  // an error if len(seed) is not SeedSize. This function is provided
    79  // for interoperability with RFC 7748. RFC 7748's private keys
    80  // correspond to seeds in this package.
    81  func NewKeyFromSeed(seed []byte) (PrivateKey, error) {
    82  	privateKey := make([]byte, PrivateKeySize)
    83  	if len(seed) != SeedSize {
    84  		return nil, errors.Errorf("unexpected seed size: %d", len(seed))
    85  	}
    86  	copy(privateKey, seed)
    87  	public, err := curve25519.X25519(seed, curve25519.Basepoint)
    88  	if err != nil {
    89  		return nil, errors.Wrap(err, "failed to compute public key")
    90  	}
    91  	copy(privateKey[SeedSize:], public)
    92  
    93  	return privateKey, nil
    94  }
    95  
    96  // GenerateKey generates a public/private key pair using entropy from rand.
    97  // If rand is nil, crypto/rand.Reader will be used.
    98  func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
    99  	if rand == nil {
   100  		rand = cryptorand.Reader
   101  	}
   102  
   103  	seed := make([]byte, SeedSize)
   104  	if _, err := io.ReadFull(rand, seed); err != nil {
   105  		return nil, nil, err
   106  	}
   107  
   108  	privateKey, err := NewKeyFromSeed(seed)
   109  	if err != nil {
   110  		return nil, nil, err
   111  	}
   112  	publicKey := make([]byte, PublicKeySize)
   113  	copy(publicKey, privateKey[SeedSize:])
   114  
   115  	return publicKey, privateKey, nil
   116  }
   117  

View as plain text