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