github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp6.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 // gfP6 implements the field of size p^6 as a cubic extension of gfP2 11 // where s³=ξ and ξ=u 12 type gfP6 struct { 13 x, y, z gfP2 // value is xs² + ys + z 14 } 15 16 func gfP6Decode(in *gfP6) *gfP6 { 17 out := &gfP6{} 18 out.x = *gfP2Decode(&in.x) 19 out.y = *gfP2Decode(&in.y) 20 out.z = *gfP2Decode(&in.z) 21 return out 22 } 23 24 func (e *gfP6) String() string { 25 return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" 26 } 27 28 func (e *gfP6) Set(a *gfP6) *gfP6 { 29 gfp6Copy(e, a) 30 return e 31 } 32 33 func (e *gfP6) SetZero() *gfP6 { 34 e.x.SetZero() 35 e.y.SetZero() 36 e.z.SetZero() 37 return e 38 } 39 40 func (e *gfP6) SetOne() *gfP6 { 41 e.x.SetZero() 42 e.y.SetZero() 43 e.z.SetOne() 44 return e 45 } 46 47 func (e *gfP6) SetS() *gfP6 { 48 e.x.SetZero() 49 e.y.SetOne() 50 e.z.SetZero() 51 return e 52 } 53 54 func (e *gfP6) SetS2() *gfP6 { 55 e.x.SetOne() 56 e.y.SetZero() 57 e.z.SetZero() 58 return e 59 } 60 61 func (e *gfP6) IsZero() bool { 62 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() 63 } 64 65 func (e *gfP6) IsOne() bool { 66 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() 67 } 68 69 func (e *gfP6) Neg(a *gfP6) *gfP6 { 70 e.x.Neg(&a.x) 71 e.y.Neg(&a.y) 72 e.z.Neg(&a.z) 73 return e 74 } 75 76 func (e *gfP6) Add(a, b *gfP6) *gfP6 { 77 e.x.Add(&a.x, &b.x) 78 e.y.Add(&a.y, &b.y) 79 e.z.Add(&a.z, &b.z) 80 return e 81 } 82 83 func (e *gfP6) Sub(a, b *gfP6) *gfP6 { 84 e.x.Sub(&a.x, &b.x) 85 e.y.Sub(&a.y, &b.y) 86 e.z.Sub(&a.z, &b.z) 87 return e 88 } 89 90 func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { 91 e.x.Mul(&a.x, b) 92 e.y.Mul(&a.y, b) 93 e.z.Mul(&a.z, b) 94 return e 95 } 96 97 func (e *gfP6) MulGfP(a *gfP6, b *gfP) *gfP6 { 98 e.x.MulScalar(&a.x, b) 99 e.y.MulScalar(&a.y, b) 100 e.z.MulScalar(&a.z, b) 101 return e 102 } 103 104 func (e *gfP6) Mul(a, b *gfP6) *gfP6 { 105 tmp := &gfP6{} 106 tmp.MulNC(a, b) 107 gfp6Copy(e, tmp) 108 return e 109 } 110 111 // Mul without value copy, will use e directly, so e can't be same as a and b. 112 func (e *gfP6) MulNC(a, b *gfP6) *gfP6 { 113 // (z0 + y0*s + x0*s²)* (z1 + y1*s + x1*s²) 114 // z0*z1 + z0*y1*s + z0*x1*s² 115 // +y0*z1*s + y0*y1*s² + y0*x1*u 116 // +x0*z1*s² + x0*y1*u + x0*x1*s*u 117 //=(z0*z1+y0*x1*u+x0*y1*u) + (z0*y1+y0*z1+x0*x1*u)s + (z0*x1 + y0*y1 + x0*z1)*s² 118 tx := &e.x 119 ty := &e.y 120 tz := &e.z 121 t, v0, v1, v2 := &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{} 122 v0.Mul(&a.z, &b.z) 123 v1.Mul(&a.y, &b.y) 124 v2.Mul(&a.x, &b.x) 125 126 t.Add(&a.y, &a.x) 127 tz.Add(&b.y, &b.x) 128 t.Mul(t, tz) 129 t.Sub(t, v1) 130 t.Sub(t, v2) 131 t.MulU1(t) 132 tz.Add(t, v0) 133 134 t.Add(&a.z, &a.y) 135 ty.Add(&b.z, &b.y) 136 ty.Mul(t, ty) 137 ty.Sub(ty, v0) 138 ty.Sub(ty, v1) 139 t.MulU1(v2) 140 ty.Add(ty, t) 141 142 t.Add(&a.z, &a.x) 143 tx.Add(&b.z, &b.x) 144 tx.Mul(tx, t) 145 tx.Sub(tx, v0) 146 tx.Add(tx, v1) 147 tx.Sub(tx, v2) 148 149 return e 150 } 151 152 // MulS returns (z + y*s + x*s²)*s 153 // = ys² + zs + xu 154 func (e *gfP6) MulS(a *gfP6) *gfP6 { 155 ty := (&gfP2{}).Set(&a.y) 156 tz := &gfP2{} 157 158 tz.x.Set(&a.x.y) 159 gfpDouble(&tz.y, &a.x.x) 160 gfpNeg(&tz.y, &tz.y) 161 162 e.y.Set(&a.z) 163 e.x.Set(ty) 164 e.z.Set(tz) 165 166 return e 167 } 168 169 func (e *gfP6) Square(a *gfP6) *gfP6 { 170 tmp := &gfP6{} 171 tmp.SquareNC(a) 172 gfp6Copy(e, tmp) 173 return e 174 } 175 176 // Square without value copy, will use e directly, so e can't be same as a. 177 func (e *gfP6) SquareNC(a *gfP6) *gfP6 { 178 // (z + y*s + x*s²)* (z + y*s + x*s²) 179 // z^2 + z*y*s + z*x*s² + y*z*s + y^2*s² + y*x*u + x*z*s² + x*y*u + x^2 *u *s 180 // (z^2 + y*x*s + x*y*u) + (z*y + y*z + u * x^2)s + (z*x + y^2 + x*z)*s² 181 // (z^2 + 2*x*y*u) + (u*x^2 + 2*y*z) * s + (y^2 + 2*x*z) * s² 182 // Karatsuba method 183 tx := &e.x 184 ty := &e.y 185 tz := &e.z 186 t, v0, v1, v2 := &gfP2{}, &gfP2{}, &gfP2{}, &gfP2{} 187 188 v0.Square(&a.z) 189 v1.Square(&a.y) 190 v2.Square(&a.x) 191 192 t.Add(&a.y, &a.x) 193 tz.Square(t) 194 tz.Sub(tz, v1) 195 tz.Sub(tz, v2) 196 tz.MulU1(tz) 197 tz.Add(tz, v0) 198 199 t.Add(&a.z, &a.y) 200 ty.Square(t) 201 ty.Sub(ty, v0) 202 ty.Sub(ty, v1) 203 t.MulU1(v2) 204 ty.Add(ty, t) 205 206 t.Add(&a.z, &a.x) 207 tx.Square(t) 208 tx.Sub(tx, v0) 209 tx.Add(tx, v1) 210 tx.Sub(tx, v2) 211 212 return e 213 } 214 215 func (e *gfP6) Exp(f *gfP6, power *big.Int) *gfP6 { 216 sum := (&gfP6{}).SetOne() 217 t := &gfP6{} 218 219 for i := power.BitLen() - 1; i >= 0; i-- { 220 t.Square(sum) 221 if power.Bit(i) != 0 { 222 sum.Mul(t, f) 223 } else { 224 sum.Set(t) 225 } 226 } 227 228 e.Set(sum) 229 return e 230 } 231 232 func (e *gfP6) Invert(a *gfP6) *gfP6 { 233 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 234 // ftp://136.206.11.249/pub/crypto/pairings.pdf 235 236 t1 := (&gfP2{}).MulU(&a.x, &a.y) 237 A := (&gfP2{}).Square(&a.z) 238 A.Sub(A, t1) 239 240 B := (&gfP2{}).SquareU(&a.x) 241 t1.Mul(&a.y, &a.z) 242 B.Sub(B, t1) 243 244 C := (&gfP2{}).Square(&a.y) 245 t1.Mul(&a.x, &a.z) 246 C.Sub(C, t1) 247 248 F := (&gfP2{}).MulU(C, &a.y) 249 t1.Mul(A, &a.z) 250 F.Add(F, t1) 251 t1.MulU(B, &a.x) 252 F.Add(F, t1) 253 254 F.Invert(F) 255 256 e.x.Mul(C, F) 257 e.y.Mul(B, F) 258 e.z.Mul(A, F) 259 return e 260 } 261 262 // (z + y*s + x*s²)^p 263 //= z^p + y^p*s*s^(p-1)+x^p*s²*(s²)^(p-1) 264 //= z^p + (s^(p-1)*y^p)*s+((s²)^(p-1)*x^p)*s² 265 //= f(z) + (s^(p-1)*f(y))*s+((s²)^(p-1)*f(x))*s² 266 // sToPMinus1^3 = p - 1 267 // sTo2PMinus2 = sToPMinus1 ^ 2 268 func (e *gfP6) Frobenius(a *gfP6) *gfP6 { 269 e.z.Conjugate(&a.z) 270 e.y.Conjugate(&a.y) 271 e.x.Conjugate(&a.x) 272 e.y.MulScalar(&e.y, sToPMinus1) 273 e.x.MulScalar(&e.x, sTo2PMinus2) 274 275 return e 276 } 277 278 // FrobeniusP2 computes (xs²+ys+z)^(p²) 279 // = z^p² + y^p²*s^p² + x^p²*s²^p² 280 // = z + y*s^p² + x * s^(2p²) 281 // = z + y*s*s^(p²-1) + x * s² * s^(2p² - 2) 282 // = z + y*s*u^((p²-1)/3) + x * s² * u^((2p² - 2)/3) 283 // uToPSquaredMinus1Over3 = sToPSquaredMinus1 284 // s^(p²-1) = s^((p-1)(p+1)) = (s^(p-1))^(p+1) = sTo2PMinus2 285 // 286 // uToPSquaredMinus1Over3 = sTo2PSquaredMinus2 287 // = sTo2PMinus2^2 288 func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { 289 e.x.MulScalar(&a.x, sTo2PSquaredMinus2) 290 e.y.MulScalar(&a.y, sToPSquaredMinus1) 291 e.z.Set(&a.z) 292 return e 293 } 294 295 // FrobeniusP4 computes (xs²+ys+z)^(p^4) 296 func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { 297 e.x.MulScalar(&a.x, sToPSquaredMinus1) 298 e.y.MulScalar(&a.y, sTo2PSquaredMinus2) 299 e.z.Set(&a.z) 300 return e 301 } 302 303 // Select sets q to p1 if cond == 1, and to p2 if cond == 0. 304 func (q *gfP6) Select(p1, p2 *gfP6, cond int) *gfP6 { 305 q.x.Select(&p1.x, &p2.x, cond) 306 q.y.Select(&p1.y, &p2.y, cond) 307 q.z.Select(&p1.z, &p2.z, cond) 308 return q 309 }