seckey.mx raw

   1  // Copyright (c) 2013-2014 The btcsuite developers
   2  // Copyright (c) 2015-2023 The Decred developers
   3  // Use of this source code is governed by an ISC
   4  // license that can be found in the LICENSE file.
   5  
   6  package secp256k1
   7  
   8  import (
   9  	"crypto/rand"
  10  	"io"
  11  )
  12  
  13  // SecretKey provides facilities for working with secp256k1 secret keys within
  14  // this package and includes functionality such as serializing and parsing them
  15  // as well as computing their associated public key.
  16  type SecretKey struct {
  17  	Key ModNScalar
  18  }
  19  
  20  // PrivateKey is a secret key.
  21  //
  22  // Deprecated: use SecretKey - secret = one person; private = two or more (you don't share secret keys!)
  23  type PrivateKey = SecretKey
  24  
  25  // NewSecretKey instantiates a new secret key from a scalar encoded as a big integer.
  26  func NewSecretKey(key *ModNScalar) *SecretKey { return &SecretKey{Key: *key} }
  27  
  28  // NewPrivateKey instantiates a new secret key from a scalar encoded as a big integer.
  29  //
  30  // Deprecated: use NewSecretKey - secret = one person; private = two or more (you don't share secret keys!)
  31  func NewPrivateKey(key *ModNScalar) *SecretKey { return NewSecretKey(key) }
  32  
  33  // SecKeyFromBytes returns a secret based on the provided byte slice which is
  34  // interpreted as an unsigned 256-bit big-endian integer in the range [0, N-1],
  35  // where N is the order of the curve.
  36  //
  37  // WARNING: This means passing a slice with more than 32 bytes is truncated and
  38  // that truncated value is reduced modulo N.  Further, 0 is not a valid secret
  39  // key.  It is up to the caller to provide a value in the appropriate range of
  40  // [1, N-1].  Failure to do so will either result in an invalid secret key or
  41  // potentially weak secret keys that have bias that could be exploited.
  42  //
  43  // This function primarily exists to provide a mechanism for converting
  44  // serialized secret keys that are already known to be good.
  45  //
  46  // Typically, callers should make use of GenerateSecretKey or
  47  // GenerateSecretKeyFromRand when creating secret keys since they properly
  48  // handle generation of appropriate values.
  49  func SecKeyFromBytes(secKeyBytes []byte) *SecretKey {
  50  	var secKey SecretKey
  51  	secKey.Key.SetByteSlice(secKeyBytes)
  52  	return &secKey
  53  }
  54  
  55  func PrivKeyFromBytes(secKeyBytes []byte) *SecretKey { return SecKeyFromBytes(secKeyBytes) }
  56  
  57  // generateSecretKey generates and returns a new secret key that is suitable
  58  // for use with secp256k1 using the provided reader as a source of entropy.  The
  59  // provided reader must be a source of cryptographically secure randomness to
  60  // avoid weak secret keys.
  61  func generateSecretKey(rand io.Reader) (*SecretKey, error) {
  62  	// The group order is close enough to 2^256 that there is only roughly a 1
  63  	// in 2^128 chance of generating an invalid secret key, so this loop will
  64  	// virtually never run more than a single iteration in practice.
  65  	var key SecretKey
  66  	var b32 [32]byte
  67  	for valid := false; !valid; {
  68  		if _, err := io.ReadFull(rand, b32[:]); err != nil {
  69  			return nil, err
  70  		}
  71  		// The secret key is only valid when it is in the range [1, N-1], where
  72  		// N is the order of the curve.
  73  		overflow := key.Key.SetBytes(&b32)
  74  		valid = (key.Key.IsZeroBit() | overflow) == 0
  75  	}
  76  	zeroArray32(&b32)
  77  	return &key, nil
  78  }
  79  
  80  // GenerateSecretKey generates and returns a new cryptographically secure secret key that is suitable for use with
  81  // secp256k1.
  82  func GenerateSecretKey() (*SecretKey, error) {
  83  	return generateSecretKey(rand.Reader())
  84  }
  85  
  86  // GeneratePrivateKey generates and returns a new cryptographically secure secret key that is suitable for use with
  87  // secp256k1.
  88  //
  89  // Deprecated: use NewSecretKey - secret = one person; private = two or more (you don't share secret keys!)
  90  func GeneratePrivateKey() (*SecretKey, error) { return GenerateSecretKey() }
  91  
  92  // GenerateSecretKeyFromRand generates a secret key that is suitable for use with secp256k1 using the provided reader as
  93  // a source of entropy. The provided reader must be a source of cryptographically secure randomness, such as
  94  // [crypto/rand.Reader], to avoid weak secret keys.
  95  func GenerateSecretKeyFromRand(rand io.Reader) (*SecretKey, error) {
  96  	return generateSecretKey(rand)
  97  }
  98  
  99  // GeneratePrivateKeyFromRand generates a secret key that is suitable for use with secp256k1 using the provided reader as
 100  // a source of entropy. The provided reader must be a source of cryptographically secure randomness, such as
 101  // [crypto/rand.Reader], to avoid weak secret keys.
 102  //
 103  // Deprecated: use GenerateSecretKeyFromRand - secret = one person; private = two or more (you don't share secret keys!)
 104  func GeneratePrivateKeyFromRand(rand io.Reader) (*SecretKey, error) { return GenerateSecretKeyFromRand(rand) }
 105  
 106  // PubKey computes and returns the public key corresponding to this secret key.
 107  func (p *SecretKey) PubKey() *PublicKey {
 108  	var result JacobianPoint
 109  	ScalarBaseMultNonConst(&p.Key, &result)
 110  	result.ToAffine()
 111  	return NewPublicKey(&result.X, &result.Y)
 112  }
 113  
 114  // Zero manually clears the memory associated with the secret key.  This can be
 115  // used to explicitly clear key material from memory for enhanced security
 116  // against memory scraping.
 117  func (p *SecretKey) Zero() { p.Key.Zero() }
 118  
 119  // SecKeyBytesLen defines the length in bytes of a serialized secret key.
 120  const SecKeyBytesLen = 32
 121  
 122  // Serialize returns the secret key as a 256-bit big-endian binary-encoded
 123  // number, padded to a length of 32 bytes.
 124  func (p *SecretKey) Serialize() []byte {
 125  	var secKeyBytes [SecKeyBytesLen]byte
 126  	p.Key.PutBytes(&secKeyBytes)
 127  	return secKeyBytes[:]
 128  }
 129