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