This repository has been archived by the owner on Aug 7, 2023. It is now read-only.
forked from decred/dcrd
/
privkey.go
202 lines (165 loc) · 5.29 KB
/
privkey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package edwards
import (
"bytes"
"crypto/ecdsa"
"crypto/rand"
"crypto/sha512"
"fmt"
"math/big"
"github.com/decred/ed25519"
)
// These constants define the lengths of serialized private keys.
const (
PrivScalarSize = 32
PrivKeyBytesLen = 64
)
// PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing
// things with the the private key without having to directly import the ecdsa
// package.
type PrivateKey struct {
ecPk *ecdsa.PrivateKey
secret *[32]byte
}
// NewPrivateKey instantiates a new private key from a scalar encoded as a
// big integer.
func NewPrivateKey(curve *TwistedEdwardsCurve, d *big.Int) *PrivateKey {
dArray := BigIntToEncodedBytes(d)
priv, _ := PrivKeyFromSecret(curve, dArray[:])
return priv
}
// GeneratePrivateKey is a wrapper for ecdsa.GenerateKey that returns a
// PrivateKey instead of the normal ecdsa.PrivateKey.
func GeneratePrivateKey(curve *TwistedEdwardsCurve) (*PrivateKey, error) {
key, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, err
}
pk := new(PrivateKey)
pk.ecPk = key
return pk, nil
}
// computeScalar obtains a private scalar from a private key.
func computeScalar(privateKey *[PrivKeyBytesLen]byte) *[PrivScalarSize]byte {
h := sha512.New()
h.Write(privateKey[:32])
digest := h.Sum(nil)
digest[0] &= 248 // Make a multiple of 8
digest[31] &= 127 // Zero the first bit of this byte
digest[31] |= 64 // Enable the seventh bit
var hBytes [PrivScalarSize]byte
copy(hBytes[:], digest)
return &hBytes
}
// PrivKeyFromBytes returns a private and public key for `curve' based on the
// private key passed as an argument as a byte slice.
func PrivKeyFromBytes(curve *TwistedEdwardsCurve,
pkBytes []byte) (*PrivateKey, *PublicKey) {
if len(pkBytes) != PrivKeyBytesLen {
return nil, nil
}
pk := copyBytes64(pkBytes)
// The ed25519 library does a weird thing where it generates a
// private key 64 bytes long, and stores the private scalar in
// the first 32 bytes and the public key in the last 32 bytes.
// So, make sure we only grab the actual scalar we care about.
privKeyBytes := pk[0:32]
pubKeyBytes := pk[32:64]
pubKey, err := ParsePubKey(curve, pubKeyBytes)
if err != nil {
return nil, nil
}
priv := &ecdsa.PrivateKey{
PublicKey: *pubKey.ToECDSA(),
D: new(big.Int).SetBytes(computeScalar(pk)[:]),
}
privEd := new(PrivateKey)
privEd.ecPk = priv
privEd.secret = copyBytes(privKeyBytes)
return privEd, (*PublicKey)(&priv.PublicKey)
}
// PrivKeyFromSecret returns a private and public key for `curve' based on the
// 32-byte private key secret passed as an argument as a byte slice.
func PrivKeyFromSecret(curve *TwistedEdwardsCurve, s []byte) (*PrivateKey,
*PublicKey) {
if len(s) != PrivKeyBytesLen/2 {
return nil, nil
}
// Instead of using rand to generate our scalar, use the scalar
// itself as a reader.
sReader := bytes.NewReader(s)
_, pk, err := ed25519.GenerateKey(sReader)
if err != nil {
return nil, nil
}
return PrivKeyFromBytes(curve, pk[:])
}
// PrivKeyFromScalar returns a private and public key for `curve' based on the
// 32-byte private scalar passed as an argument as a byte slice (encoded big
// endian int).
func PrivKeyFromScalar(curve *TwistedEdwardsCurve, p []byte) (*PrivateKey,
*PublicKey, error) {
if len(p) != PrivScalarSize {
return nil, nil, fmt.Errorf("bad private scalar size")
}
pk := new(PrivateKey)
pk.ecPk = new(ecdsa.PrivateKey)
pk.ecPk.D = new(big.Int).SetBytes(p)
// The scalar must be in the subgroup.
if pk.ecPk.D.Cmp(curve.N) > 0 {
return nil, nil, fmt.Errorf("not on subgroup (>N)")
}
// The scalar must not be zero or negative.
if pk.ecPk.D.Cmp(zero) <= 0 {
return nil, nil, fmt.Errorf("zero or negative scalar")
}
pk.ecPk.Curve = curve
pk.ecPk.PublicKey.X, pk.ecPk.PublicKey.Y =
curve.ScalarBaseMult(pk.GetD().Bytes())
if pk.ecPk.PublicKey.X == nil || pk.ecPk.PublicKey.Y == nil {
return nil, nil, fmt.Errorf("scalarbase mult failure to get pubkey")
}
pub := PublicKey(pk.ecPk.PublicKey)
return pk, &pub, nil
}
// Public returns the PublicKey corresponding to this private key.
func (p PrivateKey) Public() (*big.Int, *big.Int) {
return p.ecPk.PublicKey.X, p.ecPk.PublicKey.Y
}
// ToECDSA returns the private key as a *ecdsa.PrivateKey.
func (p PrivateKey) ToECDSA() *ecdsa.PrivateKey {
return p.ecPk
}
// Serialize returns the private key as a 32 byte big endian number.
func (p PrivateKey) Serialize() []byte {
if p.ecPk.D == nil ||
p.ecPk.PublicKey.X == nil ||
p.ecPk.PublicKey.Y == nil {
return nil
}
privateScalar := copyBytes(p.ecPk.D.Bytes())
return privateScalar[:]
}
// SerializeSecret returns the 32 byte secret along with its public key as 64
// bytes.
func (p PrivateKey) SerializeSecret() []byte {
if p.secret == nil {
return nil
}
// This is little endian.
pubX, pubY := p.Public()
spk := BigIntPointToEncodedBytes(pubX, pubY)
all := append(p.secret[:], spk[:]...)
return all
}
// GetD satisfies the chainec PrivateKey interface.
func (p PrivateKey) GetD() *big.Int {
return p.ecPk.D
}
// GetType satisfies the chainec PrivateKey interface.
func (p PrivateKey) GetType() int {
return ecTypeEdwards
}