1 // Copyright (c) 2013-2014 The btcsuite developers
2 // Copyright (c) 2015-2024 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