github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp4.go (about) 1 package bn256 2 3 import "math/big" 4 5 // For details of the algorithms used, see "Multiplication and Squaring on 6 // Pairing-Friendly Fields, Devegili et al. 7 // http://eprint.iacr.org/2006/471.pdf. 8 // 9 10 // gfP4 implements the field of size p^4 as a quadratic extension of gfP2 11 // where v²=ξ and ξ=u. 12 type gfP4 struct { 13 x, y gfP2 // value is xv+y. 14 } 15 16 func gfP4Decode(in *gfP4) *gfP4 { 17 out := &gfP4{} 18 out.x = *gfP2Decode(&in.x) 19 out.y = *gfP2Decode(&in.y) 20 return out 21 } 22 23 func (e *gfP4) String() string { 24 return "(" + e.x.String() + ", " + e.y.String() + ")" 25 } 26 27 func (e *gfP4) Set(a *gfP4) *gfP4 { 28 gfp4Copy(e, a) 29 return e 30 } 31 32 func (e *gfP4) SetZero() *gfP4 { 33 e.x.SetZero() 34 e.y.SetZero() 35 return e 36 } 37 38 func (e *gfP4) SetOne() *gfP4 { 39 e.x.SetZero() 40 e.y.SetOne() 41 return e 42 } 43 44 func (e *gfP4) SetV() *gfP4 { 45 e.x.SetOne() 46 e.y.SetZero() 47 return e 48 } 49 50 func (e *gfP4) IsZero() bool { 51 return e.x.IsZero() && e.y.IsZero() 52 } 53 54 func (e *gfP4) IsOne() bool { 55 return e.x.IsZero() && e.y.IsOne() 56 } 57 58 func (e *gfP4) Conjugate(a *gfP4) *gfP4 { 59 e.y.Set(&a.y) 60 e.x.Neg(&a.x) 61 return e 62 } 63 64 func (e *gfP4) Neg(a *gfP4) *gfP4 { 65 e.x.Neg(&a.x) 66 e.y.Neg(&a.y) 67 return e 68 } 69 70 func (e *gfP4) Add(a, b *gfP4) *gfP4 { 71 e.x.Add(&a.x, &b.x) 72 e.y.Add(&a.y, &b.y) 73 return e 74 } 75 76 func (e *gfP4) Double(a *gfP4) *gfP4 { 77 e.x.Double(&a.x) 78 e.y.Double(&a.y) 79 return e 80 } 81 82 func (e *gfP4) Triple(a *gfP4) *gfP4 { 83 e.x.Triple(&a.x) 84 e.y.Triple(&a.y) 85 return e 86 } 87 88 func (e *gfP4) Sub(a, b *gfP4) *gfP4 { 89 e.x.Sub(&a.x, &b.x) 90 e.y.Sub(&a.y, &b.y) 91 return e 92 } 93 94 func (e *gfP4) MulScalar(a *gfP4, b *gfP2) *gfP4 { 95 e.x.Mul(&a.x, b) 96 e.y.Mul(&a.y, b) 97 return e 98 } 99 100 func (e *gfP4) MulGFP(a *gfP4, b *gfP) *gfP4 { 101 e.x.MulScalar(&a.x, b) 102 e.y.MulScalar(&a.y, b) 103 return e 104 } 105 106 func (e *gfP4) Mul(a, b *gfP4) *gfP4 { 107 tmp := &gfP4{} 108 tmp.MulNC(a, b) 109 gfp4Copy(e, tmp) 110 return e 111 } 112 113 // Mul without value copy, will use e directly, so e can't be same as a and b. 114 func (e *gfP4) MulNC(a, b *gfP4) *gfP4 { 115 // "Multiplication and Squaring on Pairing-Friendly Fields" 116 // Section 4, Karatsuba method. 117 // http://eprint.iacr.org/2006/471.pdf 118 //(a0+a1*v)(b0+b1*v)=c0+c1*v, where 119 //c0 = a0*b0 +a1*b1*u 120 //c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0 121 tx := &e.x 122 ty := &e.y 123 v0, v1 := &gfP2{}, &gfP2{} 124 v0.Mul(&a.y, &b.y) 125 v1.Mul(&a.x, &b.x) 126 127 tx.Add(&a.x, &a.y) 128 ty.Add(&b.x, &b.y) 129 tx.Mul(tx, ty) 130 tx.Sub(tx, v0) 131 tx.Sub(tx, v1) 132 133 ty.MulU1(v1) 134 ty.Add(ty, v0) 135 136 return e 137 } 138 139 // MulNC2 muls a with (xv+y), this method is used in mulLine function 140 // to avoid gfP4 instance construction. e can't be same as a. 141 func (e *gfP4) MulNC2(a *gfP4, x, y *gfP2) *gfP4 { 142 // "Multiplication and Squaring on Pairing-Friendly Fields" 143 // Section 4, Karatsuba method. 144 // http://eprint.iacr.org/2006/471.pdf 145 //(a0+a1*v)(b0+b1*v)=c0+c1*v, where 146 //c0 = a0*b0 +a1*b1*u 147 //c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0 148 tx := &e.x 149 ty := &e.y 150 v0, v1 := &gfP2{}, &gfP2{} 151 v0.Mul(&a.y, y) 152 v1.Mul(&a.x, x) 153 154 tx.Add(&a.x, &a.y) 155 ty.Add(x, y) 156 tx.Mul(tx, ty) 157 tx.Sub(tx, v0) 158 tx.Sub(tx, v1) 159 160 ty.MulU1(v1) 161 ty.Add(ty, v0) 162 163 return e 164 } 165 166 // MulV: a * b * v 167 // (a0+a1*v)(b0+b1*v)*v=c0+c1*v, where 168 // (a0*b0 + a0*b1v + a1*b0*v + a1*b1*u)*v 169 // a0*b0*v + a0*b1*u + a1*b0*u + a1*b1*u*v 170 // c0 = a0*b1*u + a1*b0*u 171 // c1 = a0*b0 + a1*b1*u 172 func (e *gfP4) MulV(a, b *gfP4) *gfP4 { 173 tmp := &gfP4{} 174 tmp.MulVNC(a, b) 175 gfp4Copy(e, tmp) 176 return e 177 } 178 179 // MulV without value copy, will use e directly, so e can't be same as a and b. 180 func (e *gfP4) MulVNC(a, b *gfP4) *gfP4 { 181 tx := &e.x 182 ty := &e.y 183 v0, v1 := &gfP2{}, &gfP2{} 184 v0.Mul(&a.y, &b.y) 185 v1.Mul(&a.x, &b.x) 186 187 tx.Add(&a.x, &a.y) 188 ty.Add(&b.x, &b.y) 189 ty.Mul(tx, ty) 190 ty.Sub(ty, v0) 191 ty.Sub(ty, v1) 192 ty.MulU1(ty) 193 194 tx.MulU1(v1) 195 tx.Add(tx, v0) 196 197 return e 198 } 199 200 // MulV1: a * v 201 // (a0+a1*v)*v=c0+c1*v, where 202 // c0 = a1*u 203 // c1 = a0 204 func (e *gfP4) MulV1(a *gfP4) *gfP4 { 205 tx := &gfP2{} 206 gfp2Copy(tx, &a.y) 207 208 e.y.MulU1(&a.x) 209 gfp2Copy(&e.x, tx) 210 return e 211 } 212 213 func (e *gfP4) Square(a *gfP4) *gfP4 { 214 // Complex squaring algorithm: 215 // (xv+y)² = (x^2*u + y^2) + 2*x*y*v 216 tmp := &gfP4{} 217 tmp.SquareNC(a) 218 gfp4Copy(e, tmp) 219 return e 220 } 221 222 // Square without value copy, will use e directly, so e can't be same as a. 223 func (e *gfP4) SquareNC(a *gfP4) *gfP4 { 224 // Complex squaring algorithm: 225 // (xv+y)² = (x^2*u + y^2) + 2*x*y*v 226 // = (xu + y)(x + y) -xy(1+u) + 2xy*v 227 tx := &e.x 228 ty := &e.y 229 230 tx.SquareU(&a.x) 231 ty.Square(&a.y) 232 ty.Add(tx, ty) 233 234 tx.Mul(&a.x, &a.y) 235 tx.Add(tx, tx) 236 237 return e 238 } 239 240 // SquareV without value copy, will use e directly, so e can't be same as a. 241 // SquareV: (a^2) * v 242 // v*(xv+y)² = (x^2*u + y^2)v + 2*x*y*u 243 func (e *gfP4) SquareV(a *gfP4) *gfP4 { 244 tmp := &gfP4{} 245 tmp.SquareVNC(a) 246 gfp4Copy(e, tmp) 247 return e 248 } 249 250 func (e *gfP4) SquareVNC(a *gfP4) *gfP4 { 251 tx := &e.x 252 ty := &e.y 253 tx.SquareU(&a.x) 254 ty.Square(&a.y) 255 tx.Add(tx, ty) 256 257 ty.MulU(&a.x, &a.y) 258 ty.Add(ty, ty) 259 260 return e 261 } 262 263 func (e *gfP4) Invert(a *gfP4) *gfP4 { 264 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 265 // ftp://136.206.11.249/pub/crypto/pairings.pdf 266 tmp := &gfP4{} 267 t2 := &tmp.x 268 t1 := &tmp.y 269 270 t3 := &gfP2{} 271 272 t3.SquareU(&a.x) 273 t1.Square(&a.y) 274 t3.Sub(t3, t1) 275 t3.Invert(t3) 276 277 t1.Mul(&a.y, t3) 278 t1.Neg(t1) 279 280 t2.Mul(&a.x, t3) 281 282 gfp4Copy(e, tmp) 283 return e 284 } 285 286 func (e *gfP4) Exp(f *gfP4, power *big.Int) *gfP4 { 287 sum := (&gfP4{}).SetOne() 288 t := &gfP4{} 289 290 for i := power.BitLen() - 1; i >= 0; i-- { 291 t.Square(sum) 292 if power.Bit(i) != 0 { 293 sum.Mul(t, f) 294 } else { 295 sum.Set(t) 296 } 297 } 298 299 e.Set(sum) 300 return e 301 } 302 303 // (y+x*v)^p 304 // 305 // = y^p + x^p*v^p 306 // = f(y) + f(x) * v^p 307 // = f(y) + f(x) * v * v^(p-1) 308 func (e *gfP4) Frobenius(a *gfP4) *gfP4 { 309 tmp := &gfP4{} 310 x := &tmp.x 311 y := &tmp.y 312 313 x.Conjugate(&a.x) 314 y.Conjugate(&a.y) 315 x.MulScalar(x, vToPMinus1) 316 317 gfp4Copy(e, tmp) 318 319 return e 320 } 321 322 // (y+x*v)^(p^2) 323 // 324 // y + x*v * v^(p^2-1) 325 func (e *gfP4) FrobeniusP2(a *gfP4) *gfP4 { 326 e.Conjugate(a) 327 return e 328 } 329 330 // (y+x*v)^(p^3) 331 // 332 // = ((y+x*v)^p)^(p^2) 333 func (e *gfP4) FrobeniusP3(a *gfP4) *gfP4 { 334 tmp := &gfP4{} 335 x := &tmp.x 336 y := &tmp.y 337 x.Conjugate(&a.x) 338 y.Conjugate(&a.y) 339 x.MulScalar(x, vToPMinus1) 340 x.Neg(x) 341 342 gfp4Copy(e, tmp) 343 344 return e 345 } 346 347 // Select sets q to p1 if cond == 1, and to p2 if cond == 0. 348 func (q *gfP4) Select(p1, p2 *gfP4, cond int) *gfP4 { 349 q.x.Select(&p1.x, &p2.x, cond) 350 q.y.Select(&p1.y, &p2.y, cond) 351 return q 352 }