1
2
3
4
5 package elliptic
6
7 import (
8 "crypto/elliptic/internal/fiat"
9 "math/big"
10 )
11
12 type p521Curve struct {
13 *CurveParams
14 }
15
16 var p521 p521Curve
17 var p521Params *CurveParams
18
19 func initP521() {
20
21 p521.CurveParams = &CurveParams{Name: "P-521"}
22 p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
23 p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
24 p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
25 p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
26 p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
27 p521.BitSize = 521
28 }
29
30 func (curve p521Curve) Params() *CurveParams {
31 return curve.CurveParams
32 }
33
34 func (curve p521Curve) IsOnCurve(x, y *big.Int) bool {
35 if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
36 y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
37 return false
38 }
39
40 x1 := bigIntToFiatP521(x)
41 y1 := bigIntToFiatP521(y)
42 b := bigIntToFiatP521(curve.B)
43
44
45 x3 := new(fiat.P521Element).Square(x1)
46 x3.Mul(x3, x1)
47
48 threeX := new(fiat.P521Element).Add(x1, x1)
49 threeX.Add(threeX, x1)
50
51 x3.Sub(x3, threeX)
52 x3.Add(x3, b)
53
54
55 y2 := new(fiat.P521Element).Square(y1)
56
57 return x3.Equal(y2) == 1
58 }
59
60 type p521Point struct {
61 x, y, z *fiat.P521Element
62 }
63
64 func fiatP521ToBigInt(x *fiat.P521Element) *big.Int {
65 xBytes := x.Bytes()
66 for i := range xBytes[:len(xBytes)/2] {
67 xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i]
68 }
69 return new(big.Int).SetBytes(xBytes)
70 }
71
72
73
74
75 func (curve p521Curve) affineFromJacobian(p *p521Point) (x, y *big.Int) {
76 if p.z.IsZero() == 1 {
77 return new(big.Int), new(big.Int)
78 }
79
80 zinv := new(fiat.P521Element).Invert(p.z)
81 zinvsq := new(fiat.P521Element).Mul(zinv, zinv)
82
83 xx := new(fiat.P521Element).Mul(p.x, zinvsq)
84 zinvsq.Mul(zinvsq, zinv)
85 yy := new(fiat.P521Element).Mul(p.y, zinvsq)
86
87 return fiatP521ToBigInt(xx), fiatP521ToBigInt(yy)
88 }
89
90 func bigIntToFiatP521(x *big.Int) *fiat.P521Element {
91 xBytes := new(big.Int).Mod(x, p521.P).FillBytes(make([]byte, 66))
92 for i := range xBytes[:len(xBytes)/2] {
93 xBytes[i], xBytes[len(xBytes)-i-1] = xBytes[len(xBytes)-i-1], xBytes[i]
94 }
95 x1, err := new(fiat.P521Element).SetBytes(xBytes)
96 if err != nil {
97
98
99 panic("internal error: bigIntToFiatP521")
100 }
101 return x1
102 }
103
104
105
106
107 func (curve p521Curve) jacobianFromAffine(x, y *big.Int) *p521Point {
108
109
110 if x.Sign() == 0 && y.Sign() == 0 {
111 return &p521Point{
112 x: new(fiat.P521Element),
113 y: new(fiat.P521Element),
114 z: new(fiat.P521Element),
115 }
116 }
117 return &p521Point{
118 x: bigIntToFiatP521(x),
119 y: bigIntToFiatP521(y),
120 z: new(fiat.P521Element).One(),
121 }
122 }
123
124 func (curve p521Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
125 p1 := curve.jacobianFromAffine(x1, y1)
126 p2 := curve.jacobianFromAffine(x2, y2)
127 return curve.affineFromJacobian(p1.addJacobian(p1, p2))
128 }
129
130
131 func (q *p521Point) addJacobian(p1, p2 *p521Point) *p521Point {
132
133 z1IsZero := p1.z.IsZero()
134 z2IsZero := p2.z.IsZero()
135
136 z1z1 := new(fiat.P521Element).Square(p1.z)
137 z2z2 := new(fiat.P521Element).Square(p2.z)
138
139 u1 := new(fiat.P521Element).Mul(p1.x, z2z2)
140 u2 := new(fiat.P521Element).Mul(p2.x, z1z1)
141 h := new(fiat.P521Element).Sub(u2, u1)
142 xEqual := h.IsZero() == 1
143 i := new(fiat.P521Element).Add(h, h)
144 i.Square(i)
145 j := new(fiat.P521Element).Mul(h, i)
146
147 s1 := new(fiat.P521Element).Mul(p1.y, p2.z)
148 s1.Mul(s1, z2z2)
149 s2 := new(fiat.P521Element).Mul(p2.y, p1.z)
150 s2.Mul(s2, z1z1)
151 r := new(fiat.P521Element).Sub(s2, s1)
152 yEqual := r.IsZero() == 1
153 if xEqual && yEqual && z1IsZero == 0 && z2IsZero == 0 {
154 return q.doubleJacobian(p1)
155 }
156 r.Add(r, r)
157 v := new(fiat.P521Element).Mul(u1, i)
158
159 x := new(fiat.P521Element).Set(r)
160 x.Square(x)
161 x.Sub(x, j)
162 x.Sub(x, v)
163 x.Sub(x, v)
164
165 y := new(fiat.P521Element).Set(r)
166 v.Sub(v, x)
167 y.Mul(y, v)
168 s1.Mul(s1, j)
169 s1.Add(s1, s1)
170 y.Sub(y, s1)
171
172 z := new(fiat.P521Element).Add(p1.z, p2.z)
173 z.Square(z)
174 z.Sub(z, z1z1)
175 z.Sub(z, z2z2)
176 z.Mul(z, h)
177
178 x.Select(p2.x, x, z1IsZero)
179 x.Select(p1.x, x, z2IsZero)
180 y.Select(p2.y, y, z1IsZero)
181 y.Select(p1.y, y, z2IsZero)
182 z.Select(p2.z, z, z1IsZero)
183 z.Select(p1.z, z, z2IsZero)
184
185 q.x.Set(x)
186 q.y.Set(y)
187 q.z.Set(z)
188 return q
189 }
190
191 func (curve p521Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
192 p := curve.jacobianFromAffine(x1, y1)
193 return curve.affineFromJacobian(p.doubleJacobian(p))
194 }
195
196
197 func (q *p521Point) doubleJacobian(p *p521Point) *p521Point {
198
199 delta := new(fiat.P521Element).Square(p.z)
200 gamma := new(fiat.P521Element).Square(p.y)
201 alpha := new(fiat.P521Element).Sub(p.x, delta)
202 alpha2 := new(fiat.P521Element).Add(p.x, delta)
203 alpha.Mul(alpha, alpha2)
204 alpha2.Set(alpha)
205 alpha.Add(alpha, alpha)
206 alpha.Add(alpha, alpha2)
207
208 beta := alpha2.Mul(p.x, gamma)
209
210 q.x.Square(alpha)
211 beta8 := new(fiat.P521Element).Add(beta, beta)
212 beta8.Add(beta8, beta8)
213 beta8.Add(beta8, beta8)
214 q.x.Sub(q.x, beta8)
215
216 q.z.Add(p.y, p.z)
217 q.z.Square(q.z)
218 q.z.Sub(q.z, gamma)
219 q.z.Sub(q.z, delta)
220
221 beta.Add(beta, beta)
222 beta.Add(beta, beta)
223 beta.Sub(beta, q.x)
224 q.y.Mul(alpha, beta)
225
226 gamma.Square(gamma)
227 gamma.Add(gamma, gamma)
228 gamma.Add(gamma, gamma)
229 gamma.Add(gamma, gamma)
230
231 q.y.Sub(q.y, gamma)
232
233 return q
234 }
235
236 func (curve p521Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
237 B := curve.jacobianFromAffine(Bx, By)
238 p, t := &p521Point{
239 x: new(fiat.P521Element),
240 y: new(fiat.P521Element),
241 z: new(fiat.P521Element),
242 }, &p521Point{
243 x: new(fiat.P521Element),
244 y: new(fiat.P521Element),
245 z: new(fiat.P521Element),
246 }
247
248 for _, byte := range scalar {
249 for bitNum := 0; bitNum < 8; bitNum++ {
250 p.doubleJacobian(p)
251 bit := (byte >> (7 - bitNum)) & 1
252 t.addJacobian(p, B)
253 p.x.Select(t.x, p.x, int(bit))
254 p.y.Select(t.y, p.y, int(bit))
255 p.z.Select(t.z, p.z, int(bit))
256 }
257 }
258
259 return curve.affineFromJacobian(p)
260 }
261
262 func (curve p521Curve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
263 return curve.ScalarMult(curve.Gx, curve.Gy, k)
264 }
265
View as plain text