1
2
3
4
5 package secp256k1
6
7
8
9
10
11
12
13 import (
14 "crypto/ecdsa"
15 "crypto/elliptic"
16 "math/big"
17 )
18
19
20 type CurveParams struct {
21
22 P *big.Int
23
24
25 N *big.Int
26
27
28 Gx, Gy *big.Int
29
30
31 BitSize int
32
33
34 H int
35
36
37
38 ByteSize int
39 }
40
41
42 var curveParams = CurveParams{
43 P: fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),
44 N: fromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
45 Gx: fromHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),
46 Gy: fromHex("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"),
47 BitSize: 256,
48 H: 1,
49 ByteSize: 256 / 8,
50 }
51
52
53 func Params() *CurveParams {
54 return &curveParams
55 }
56
57
58
59 type KoblitzCurve struct {
60 *elliptic.CurveParams
61 }
62
63
64
65 func bigAffineToJacobian(x, y *big.Int, result *JacobianPoint) {
66 result.X.SetByteSlice(x.Bytes())
67 result.Y.SetByteSlice(y.Bytes())
68 result.Z.SetInt(1)
69 }
70
71
72
73 func jacobianToBigAffine(point *JacobianPoint) (*big.Int, *big.Int) {
74 point.ToAffine()
75
76
77 x3, y3 := new(big.Int), new(big.Int)
78 x3.SetBytes(point.X.Bytes()[:])
79 y3.SetBytes(point.Y.Bytes()[:])
80 return x3, y3
81 }
82
83
84
85
86 func (curve *KoblitzCurve) Params() *elliptic.CurveParams {
87 return curve.CurveParams
88 }
89
90
91
92
93
94 func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool {
95
96 var point JacobianPoint
97 bigAffineToJacobian(x, y, &point)
98 return isOnCurve(&point.X, &point.Y)
99 }
100
101
102
103
104 func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
105
106
107 if x1.Sign() == 0 && y1.Sign() == 0 {
108 return x2, y2
109 }
110 if x2.Sign() == 0 && y2.Sign() == 0 {
111 return x1, y1
112 }
113
114
115
116
117 var p1, p2, result JacobianPoint
118 bigAffineToJacobian(x1, y1, &p1)
119 bigAffineToJacobian(x2, y2, &p2)
120 AddNonConst(&p1, &p2, &result)
121 return jacobianToBigAffine(&result)
122 }
123
124
125
126
127 func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
128 if y1.Sign() == 0 {
129 return new(big.Int), new(big.Int)
130 }
131
132
133
134
135 var point, result JacobianPoint
136 bigAffineToJacobian(x1, y1, &point)
137 DoubleNonConst(&point, &result)
138 return jacobianToBigAffine(&result)
139 }
140
141
142
143
144 func moduloReduce(k []byte) []byte {
145
146
147 if len(k) > curveParams.ByteSize {
148 tmpK := new(big.Int).SetBytes(k)
149 tmpK.Mod(tmpK, curveParams.N)
150 return tmpK.Bytes()
151 }
152
153 return k
154 }
155
156
157
158
159 func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
160
161
162
163 var kModN ModNScalar
164 kModN.SetByteSlice(moduloReduce(k))
165 var point, result JacobianPoint
166 bigAffineToJacobian(Bx, By, &point)
167 ScalarMultNonConst(&kModN, &point, &result)
168 return jacobianToBigAffine(&result)
169 }
170
171
172
173
174
175 func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
176
177
178 var kModN ModNScalar
179 kModN.SetByteSlice(moduloReduce(k))
180 var result JacobianPoint
181 ScalarBaseMultNonConst(&kModN, &result)
182 return jacobianToBigAffine(&result)
183 }
184
185
186 func (p *PublicKey) X() *big.Int {
187 return new(big.Int).SetBytes(p.x.Bytes()[:])
188 }
189
190
191 func (p *PublicKey) Y() *big.Int {
192 return new(big.Int).SetBytes(p.y.Bytes()[:])
193 }
194
195
196 func (p *PublicKey) ToECDSA() *ecdsa.PublicKey {
197 return &ecdsa.PublicKey{
198 Curve: S256(),
199 X: p.X(),
200 Y: p.Y(),
201 }
202 }
203
204
205 func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey {
206 var privKeyBytes [PrivKeyBytesLen]byte
207 p.Key.PutBytes(&privKeyBytes)
208 var result JacobianPoint
209 ScalarBaseMultNonConst(&p.Key, &result)
210 x, y := jacobianToBigAffine(&result)
211 newPrivKey := &ecdsa.PrivateKey{
212 PublicKey: ecdsa.PublicKey{
213 Curve: S256(),
214 X: x,
215 Y: y,
216 },
217 D: new(big.Int).SetBytes(privKeyBytes[:]),
218 }
219 zeroArray32(&privKeyBytes)
220 return newPrivKey
221 }
222
223
224
225
226
227 func fromHex(s string) *big.Int {
228 if s == "" {
229 return big.NewInt(0)
230 }
231 r, ok := new(big.Int).SetString(s, 16)
232 if !ok {
233 panic("invalid hex in source file: " + s)
234 }
235 return r
236 }
237
238
239
240 var secp256k1 = &KoblitzCurve{
241 CurveParams: &elliptic.CurveParams{
242 P: curveParams.P,
243 N: curveParams.N,
244 B: fromHex("0000000000000000000000000000000000000000000000000000000000000007"),
245 Gx: curveParams.Gx,
246 Gy: curveParams.Gy,
247 BitSize: curveParams.BitSize,
248 Name: "secp256k1",
249 },
250 }
251
252
253 func S256() *KoblitzCurve {
254 return secp256k1
255 }
256
View as plain text