eckey.go raw
1 package p256k1
2
3 import (
4 "crypto/rand"
5 "errors"
6 )
7
8 // ECSeckeyVerify verifies that a 32-byte array is a valid secret key
9 func ECSeckeyVerify(seckey []byte) bool {
10 if len(seckey) != 32 {
11 return false
12 }
13
14 var scalar Scalar
15 return scalar.setB32Seckey(seckey)
16 }
17
18 // ECSeckeyNegate negates a secret key in place
19 func ECSeckeyNegate(seckey []byte) bool {
20 if len(seckey) != 32 {
21 return false
22 }
23
24 var scalar Scalar
25 if !scalar.setB32Seckey(seckey) {
26 return false
27 }
28
29 scalar.negate(&scalar)
30 scalar.getB32(seckey)
31 return true
32 }
33
34 // ECSeckeyGenerate generates a new random secret key
35 func ECSeckeyGenerate() ([]byte, error) {
36 seckey := make([]byte, 32)
37 for {
38 if _, err := rand.Read(seckey); err != nil {
39 return nil, err
40 }
41
42 if ECSeckeyVerify(seckey) {
43 return seckey, nil
44 }
45 }
46 }
47
48 // ECKeyPairGenerate generates a new key pair (private key and public key)
49 func ECKeyPairGenerate() (seckey []byte, pubkey *PublicKey, err error) {
50 seckey, err = ECSeckeyGenerate()
51 if err != nil {
52 return nil, nil, err
53 }
54
55 pubkey = &PublicKey{}
56 if err := ECPubkeyCreate(pubkey, seckey); err != nil {
57 return nil, nil, err
58 }
59
60 return seckey, pubkey, nil
61 }
62
63 // ECSeckeyTweakAdd adds a tweak to a secret key: seckey = seckey + tweak mod n
64 func ECSeckeyTweakAdd(seckey []byte, tweak []byte) error {
65 if len(seckey) != 32 {
66 return errors.New("secret key must be 32 bytes")
67 }
68 if len(tweak) != 32 {
69 return errors.New("tweak must be 32 bytes")
70 }
71
72 var sec, tw Scalar
73 if !sec.setB32Seckey(seckey) {
74 return errors.New("invalid secret key")
75 }
76 if !tw.setB32Seckey(tweak) {
77 return errors.New("invalid tweak")
78 }
79
80 // Add tweak
81 sec.add(&sec, &tw)
82
83 // Check if result is valid
84 if sec.isZero() {
85 return errors.New("resulting secret key is zero")
86 }
87
88 // Get result
89 sec.getB32(seckey)
90 return nil
91 }
92
93 // ECSeckeyTweakMul multiplies a secret key by a tweak: seckey = seckey * tweak mod n
94 func ECSeckeyTweakMul(seckey []byte, tweak []byte) error {
95 if len(seckey) != 32 {
96 return errors.New("secret key must be 32 bytes")
97 }
98 if len(tweak) != 32 {
99 return errors.New("tweak must be 32 bytes")
100 }
101
102 var sec, tw Scalar
103 if !sec.setB32Seckey(seckey) {
104 return errors.New("invalid secret key")
105 }
106 if !tw.setB32Seckey(tweak) {
107 return errors.New("invalid tweak")
108 }
109
110 // Multiply by tweak
111 sec.mul(&sec, &tw)
112
113 // Check if result is valid
114 if sec.isZero() {
115 return errors.New("resulting secret key is zero")
116 }
117
118 // Get result
119 sec.getB32(seckey)
120 return nil
121 }
122
123 // ECPubkeyTweakAdd adds a tweak to a public key: pubkey = pubkey + tweak*G
124 func ECPubkeyTweakAdd(pubkey *PublicKey, tweak []byte) error {
125 if len(tweak) != 32 {
126 return errors.New("tweak must be 32 bytes")
127 }
128
129 var tw Scalar
130 if !tw.setB32Seckey(tweak) {
131 return errors.New("invalid tweak")
132 }
133
134 // Load public key
135 var pubkeyPoint GroupElementAffine
136 pubkeyPoint.fromBytes(pubkey.data[:])
137 if pubkeyPoint.isInfinity() {
138 return errors.New("invalid public key")
139 }
140
141 // Compute tweak*G
142 var tweakG GroupElementJacobian
143 EcmultGen(&tweakG, &tw)
144
145 // Add to public key
146 var pubkeyJac GroupElementJacobian
147 pubkeyJac.setGE(&pubkeyPoint)
148
149 // result = pubkey + tweak*G
150 var result GroupElementJacobian
151 result.addVar(&pubkeyJac, &tweakG)
152
153 // Check if result is infinity
154 if result.isInfinity() {
155 return errors.New("resulting public key is infinity")
156 }
157
158 // Convert back to affine and store
159 var resultAff GroupElementAffine
160 resultAff.setGEJ(&result)
161 resultAff.toBytes(pubkey.data[:])
162
163 return nil
164 }
165
166 // ECPubkeyTweakMul multiplies a public key by a tweak: pubkey = pubkey * tweak
167 func ECPubkeyTweakMul(pubkey *PublicKey, tweak []byte) error {
168 if len(tweak) != 32 {
169 return errors.New("tweak must be 32 bytes")
170 }
171
172 var tw Scalar
173 if !tw.setB32Seckey(tweak) {
174 return errors.New("invalid tweak")
175 }
176
177 // Load public key
178 var pubkeyPoint GroupElementAffine
179 pubkeyPoint.fromBytes(pubkey.data[:])
180 if pubkeyPoint.isInfinity() {
181 return errors.New("invalid public key")
182 }
183
184 // Multiply by tweak using binary method
185 var pubkeyJac GroupElementJacobian
186 pubkeyJac.setGE(&pubkeyPoint)
187
188 var result GroupElementJacobian
189 result.setInfinity()
190 var base GroupElementJacobian
191 base = pubkeyJac
192
193 // Simple binary method
194 for i := 0; i < 256; i++ {
195 if i > 0 {
196 result.double(&result)
197 }
198 bit := tw.getBits(uint(255-i), 1)
199 if bit != 0 {
200 if result.isInfinity() {
201 result = base
202 } else {
203 result.addVar(&result, &base)
204 }
205 }
206 }
207
208 // Check if result is infinity
209 if result.isInfinity() {
210 return errors.New("resulting public key is infinity")
211 }
212
213 // Convert back to affine and store
214 var resultAff GroupElementAffine
215 resultAff.setGEJ(&result)
216 resultAff.toBytes(pubkey.data[:])
217
218 return nil
219 }
220
221