github.com/emmansun/gmsm@v0.29.1/sm9/bn256/curve.go (about) 1 package bn256 2 3 import ( 4 "crypto/subtle" 5 "math/big" 6 ) 7 8 // curvePoint implements the elliptic curve y²=x³+5. Points are kept in Jacobian 9 // form and t=z² when valid. G₁ is the set of points of this curve on GF(p). 10 type curvePoint struct { 11 x, y, z, t gfP 12 } 13 14 var curveB = newGFp(5) 15 var threeCurveB = newGFp(3 * 5) 16 17 // curveGen is the generator of G₁. 18 var curveGen = &curvePoint{ 19 x: *fromBigInt(bigFromHex("93DE051D62BF718FF5ED0704487D01D6E1E4086909DC3280E8C4E4817C66DDDD")), 20 y: *fromBigInt(bigFromHex("21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616")), 21 z: *one, 22 t: *one, 23 } 24 25 func (c *curvePoint) String() string { 26 c.MakeAffine() 27 x, y := &gfP{}, &gfP{} 28 montDecode(x, &c.x) 29 montDecode(y, &c.y) 30 return "(" + x.String() + ", " + y.String() + ")" 31 } 32 33 func (c *curvePoint) Set(a *curvePoint) { 34 c.x.Set(&a.x) 35 c.y.Set(&a.y) 36 c.z.Set(&a.z) 37 c.t.Set(&a.t) 38 } 39 40 func (c *curvePoint) polynomial(x *gfP) *gfP { 41 x3 := &gfP{} 42 gfpSqr(x3, x, 1) 43 gfpMul(x3, x3, x) 44 gfpAdd(x3, x3, curveB) 45 return x3 46 } 47 48 // IsOnCurve returns true if c is on the curve. 49 func (c *curvePoint) IsOnCurve() bool { 50 c.MakeAffine() 51 if c.IsInfinity() { // TBC: This is not same as golang elliptic 52 return true 53 } 54 55 y2 := &gfP{} 56 gfpSqr(y2, &c.y, 1) 57 58 x3 := c.polynomial(&c.x) 59 60 return y2.Equal(x3) == 1 61 } 62 63 func NewCurvePoint() *curvePoint { 64 c := &curvePoint{} 65 c.SetInfinity() 66 return c 67 } 68 69 func NewCurveGenerator() *curvePoint { 70 c := &curvePoint{} 71 c.Set(curveGen) 72 return c 73 } 74 75 func (c *curvePoint) SetInfinity() { 76 c.x.Set(zero) 77 c.y.Set(one) 78 c.z.Set(zero) 79 c.t.Set(zero) 80 } 81 82 func (c *curvePoint) IsInfinity() bool { 83 return c.z.Equal(zero) == 1 84 } 85 86 func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) { 87 sum, t := &curvePoint{}, &curvePoint{} 88 sum.SetInfinity() 89 90 for i := scalar.BitLen(); i >= 0; i-- { 91 t.Double(sum) 92 if scalar.Bit(i) != 0 { 93 sum.Add(t, a) 94 } else { 95 sum.Set(t) 96 } 97 } 98 99 c.Set(sum) 100 } 101 102 // MakeAffine reverses the Jacobian transform. 103 // the Jacobian coordinates are (x1, y1, z1) 104 // where x = x1/z1² and y = y1/z1³. 105 func (c *curvePoint) AffineFromJacobian() { 106 if c.z.Equal(one) == 1 { 107 return 108 } else if c.z.Equal(zero) == 1 { 109 c.x.Set(zero) 110 c.y.Set(one) 111 c.t.Set(zero) 112 return 113 } 114 115 zInv := &gfP{} 116 zInv.Invert(&c.z) 117 118 t, zInv2 := &gfP{}, &gfP{} 119 gfpMul(t, &c.y, zInv) // t = y/z 120 gfpSqr(zInv2, zInv, 1) 121 122 gfpMul(&c.x, &c.x, zInv2) // x = x / z^2 123 gfpMul(&c.y, t, zInv2) // y = y / z^3 124 125 c.z.Set(one) 126 c.t.Set(one) 127 } 128 129 func (c *curvePoint) Neg(a *curvePoint) { 130 c.x.Set(&a.x) 131 gfpNeg(&c.y, &a.y) 132 c.z.Set(&a.z) 133 c.t.Set(zero) 134 } 135 136 // A curvePointTable holds the first 15 multiples of a point at offset -1, so [1]P 137 // is at table[0], [15]P is at table[14], and [0]P is implicitly the identity 138 // point. 139 type curvePointTable [15]*curvePoint 140 141 // Select selects the n-th multiple of the table base point into p. It works in 142 // constant time by iterating over every entry of the table. n must be in [0, 15]. 143 func (table *curvePointTable) Select(p *curvePoint, n uint8) { 144 if n >= 16 { 145 panic("sm9: internal error: curvePointTable called with out-of-bounds value") 146 } 147 p.SetInfinity() 148 for i, f := range table { 149 cond := subtle.ConstantTimeByteEq(uint8(i+1), n) 150 curvePointMovCond(p, f, p, cond) 151 } 152 } 153 154 // Equal compare e and other 155 func (e *curvePoint) Equal(other *curvePoint) bool { 156 return e.x.Equal(&other.x) == 1 && 157 e.y.Equal(&other.y) == 1 && 158 e.z.Equal(&other.z) == 1 && 159 e.t.Equal(&other.t) == 1 160 } 161 162 // Below methods are POC yet, the line add/double functions are still based on 163 // Jacobian coordination. 164 func (c *curvePoint) Add(p1, p2 *curvePoint) { 165 curvePointAddComplete(c, p1, p2) 166 } 167 168 func (c *curvePoint) AddComplete(p1, p2 *curvePoint) { 169 curvePointAddComplete(c, p1, p2) 170 } 171 172 func (c *curvePoint) Double(p *curvePoint) { 173 curvePointDoubleComplete(c, p) 174 } 175 176 func (c *curvePoint) DoubleComplete(p *curvePoint) { 177 curvePointDoubleComplete(c, p) 178 } 179 180 // MakeAffine reverses the Projective transform. 181 // A = 1/Z1 182 // X3 = A*X1 183 // Y3 = A*Y1 184 // Z3 = 1 185 func (c *curvePoint) MakeAffine() { 186 // TODO: do we need to change it to constant-time implementation? 187 if c.z.Equal(one) == 1 { 188 return 189 } else if c.z.Equal(zero) == 1 { 190 c.x.Set(zero) 191 c.y.Set(one) 192 c.t.Set(zero) 193 return 194 } 195 zInv := &gfP{} 196 zInv.Invert(&c.z) 197 gfpMul(&c.x, &c.x, zInv) 198 gfpMul(&c.y, &c.y, zInv) 199 c.z.Set(one) 200 c.t.Set(one) 201 } 202 203 func (c *curvePoint) AffineFromProjective() { 204 c.MakeAffine() 205 } 206 207 func curvePointDouble(c, a *curvePoint) { 208 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3 209 A, B, C := &gfP{}, &gfP{}, &gfP{} 210 gfpSqr(A, &a.x, 1) 211 gfpSqr(B, &a.y, 1) 212 gfpSqr(C, B, 1) 213 214 t := &gfP{} 215 gfpAdd(B, &a.x, B) 216 gfpSqr(t, B, 1) 217 gfpSub(B, t, A) 218 gfpSub(t, B, C) 219 220 d, e := &gfP{}, &gfP{} 221 gfpDouble(d, t) 222 gfpDouble(B, A) 223 gfpAdd(e, B, A) 224 gfpSqr(A, e, 1) 225 226 gfpDouble(B, d) 227 gfpSub(&c.x, A, B) 228 229 gfpMul(&c.z, &a.y, &a.z) 230 gfpDouble(&c.z, &c.z) 231 232 gfpDouble(B, C) 233 gfpDouble(t, B) 234 gfpDouble(B, t) 235 gfpSub(&c.y, d, &c.x) 236 gfpMul(t, e, &c.y) 237 gfpSub(&c.y, t, B) 238 } 239 240 func curvePointAdd(c, a, b *curvePoint) int { 241 // See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3 242 var pointEq int 243 // Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2] 244 // by [u1:s1:z1·z2] and [u2:s2:z1·z2] 245 // where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³ 246 z12, z22 := &gfP{}, &gfP{} 247 gfpSqr(z12, &a.z, 1) 248 gfpSqr(z22, &b.z, 1) 249 250 u1, u2 := &gfP{}, &gfP{} 251 gfpMul(u1, &a.x, z22) 252 gfpMul(u2, &b.x, z12) 253 254 t, s1 := &gfP{}, &gfP{} 255 gfpMul(t, &b.z, z22) 256 gfpMul(s1, &a.y, t) 257 258 s2 := &gfP{} 259 gfpMul(t, &a.z, z12) 260 gfpMul(s2, &b.y, t) 261 262 // Compute x = (2h)²(s²-u1-u2) 263 // where s = (s2-s1)/(u2-u1) is the slope of the line through 264 // (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below. 265 // This is also: 266 // 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1) 267 // = r² - j - 2v 268 // with the notations below. 269 h := &gfP{} 270 gfpSub(h, u2, u1) 271 272 gfpDouble(t, h) 273 // i = 4h² 274 i := &gfP{} 275 gfpSqr(i, t, 1) 276 // j = 4h³ 277 j := &gfP{} 278 gfpMul(j, h, i) 279 280 gfpSub(t, s2, s1) 281 282 pointEq = h.Equal(zero) & t.Equal(zero) 283 284 r := &gfP{} 285 gfpDouble(r, t) 286 287 v := &gfP{} 288 gfpMul(v, u1, i) 289 290 // t4 = 4(s2-s1)² 291 t4, t6 := &gfP{}, &gfP{} 292 gfpSqr(t4, r, 1) 293 gfpDouble(t, v) 294 gfpSub(t6, t4, j) 295 296 gfpSub(&c.x, t6, t) 297 298 // Set y = -(2h)³(s1 + s*(x/4h²-u1)) 299 // This is also 300 // y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j 301 gfpSub(t, v, &c.x) // t7 302 gfpMul(t4, s1, j) // t8 303 gfpDouble(t6, t4) // t9 304 gfpMul(t4, r, t) // t10 305 gfpSub(&c.y, t4, t6) 306 307 // Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2 308 gfpAdd(t, &a.z, &b.z) // t11 309 gfpSqr(t4, t, 1) // t12 310 gfpSub(t, t4, z12) // t13 311 gfpSub(t4, t, z22) // t14 312 gfpMul(&c.z, t4, h) 313 314 return pointEq 315 }