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