github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp2.go (about) 1 package bn256 2 3 import ( 4 "math/big" 5 ) 6 7 // For details of the algorithms used, see "Multiplication and Squaring on 8 // Pairing-Friendly Fields, Devegili et al. 9 // http://eprint.iacr.org/2006/471.pdf. 10 11 // gfP2 implements a field of size p² as a quadratic extension of the base field 12 // where u²=-2, beta=-2. 13 type gfP2 struct { 14 x, y gfP // value is xu+y. 15 } 16 17 func gfP2Decode(in *gfP2) *gfP2 { 18 out := &gfP2{} 19 montDecode(&out.x, &in.x) 20 montDecode(&out.y, &in.y) 21 return out 22 } 23 24 func (e *gfP2) String() string { 25 return "(" + e.x.String() + ", " + e.y.String() + ")" 26 } 27 28 func (e *gfP2) Set(a *gfP2) *gfP2 { 29 gfp2Copy(e, a) 30 return e 31 } 32 33 func (e *gfP2) SetZero() *gfP2 { 34 e.x.Set(zero) 35 e.y.Set(zero) 36 return e 37 } 38 39 func (e *gfP2) SetOne() *gfP2 { 40 e.x.Set(zero) 41 e.y.Set(one) 42 return e 43 } 44 45 func (e *gfP2) SetU() *gfP2 { 46 e.x.Set(one) 47 e.y.Set(zero) 48 return e 49 } 50 51 func (e *gfP2) SetFrobConstant() *gfP2 { 52 e.x.Set(zero) 53 e.y.Set(frobConstant) 54 return e 55 } 56 57 func (e *gfP2) Equal(t *gfP2) int { 58 var acc uint64 59 for i := range e.x { 60 acc |= e.x[i] ^ t.x[i] 61 } 62 for i := range e.y { 63 acc |= e.y[i] ^ t.y[i] 64 } 65 return uint64IsZero(acc) 66 } 67 68 func (e *gfP2) IsZero() bool { 69 return (e.x.Equal(zero) == 1) && (e.y.Equal(zero) == 1) 70 } 71 72 func (e *gfP2) IsOne() bool { 73 return (e.x.Equal(zero) == 1) && (e.y.Equal(one) == 1) 74 } 75 76 func (e *gfP2) Conjugate(a *gfP2) *gfP2 { 77 e.y.Set(&a.y) 78 gfpNeg(&e.x, &a.x) 79 return e 80 } 81 82 func (e *gfP2) Neg(a *gfP2) *gfP2 { 83 gfpNeg(&e.x, &a.x) 84 gfpNeg(&e.y, &a.y) 85 return e 86 } 87 88 func (e *gfP2) Add(a, b *gfP2) *gfP2 { 89 gfpAdd(&e.x, &a.x, &b.x) 90 gfpAdd(&e.y, &a.y, &b.y) 91 return e 92 } 93 94 func (e *gfP2) Sub(a, b *gfP2) *gfP2 { 95 gfpSub(&e.x, &a.x, &b.x) 96 gfpSub(&e.y, &a.y, &b.y) 97 return e 98 } 99 100 func (e *gfP2) Double(a *gfP2) *gfP2 { 101 gfpDouble(&e.x, &a.x) 102 gfpDouble(&e.y, &a.y) 103 return e 104 } 105 106 func (e *gfP2) Triple(a *gfP2) *gfP2 { 107 gfpTriple(&e.x, &a.x) 108 gfpTriple(&e.y, &a.y) 109 return e 110 } 111 112 // See "Multiplication and Squaring in Pairing-Friendly Fields", 113 // http://eprint.iacr.org/2006/471.pdf 114 // The Karatsuba method 115 // (a0+a1*u)(b0+b1*u)=c0+c1*u, where 116 // c0 = a0*b0 - 2a1*b1 117 // c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0 118 func (e *gfP2) Mul(a, b *gfP2) *gfP2 { 119 gfp2Mul(e, a, b) 120 return e 121 } 122 123 // MulU without value copy, will use e directly, so e can't be same as a and b. 124 // MulU: a * b * u 125 // (a0+a1*u)(b0+b1*u)*u=c0+c1*u, where 126 // c1 = (a0*b0 - 2a1*b1)u 127 // c0 = -2 * ((a0 + a1)(b0 + b1) - a0*b0 - a1*b1) = -2 * (a0*b1 + a1*b0) 128 func (e *gfP2) MulU(a, b *gfP2) *gfP2 { 129 gfp2MulU(e, a, b) 130 return e 131 } 132 133 // MulU1: a * u 134 // (a0+a1*u)u=c0+c1*u, where 135 // c1 = a0 136 // c0 = -2a1 137 func (e *gfP2) MulU1(a *gfP2) *gfP2 { 138 gfp2MulU1(e, a) 139 return e 140 } 141 142 func (e *gfP2) Square(a *gfP2) *gfP2 { 143 // Complex squaring algorithm: 144 // (xu+y)² = y^2-2*x^2 + 2*u*x*y 145 gfp2Square(e, a) 146 return e 147 } 148 149 func (e *gfP2) SquareU(a *gfP2) *gfP2 { 150 // Complex squaring algorithm: 151 // (xu+y)²*u = (y^2-2*x^2)u - 4*x*y 152 gfp2SquareU(e, a) 153 return e 154 } 155 156 func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 { 157 gfpMul(&e.x, &a.x, b) 158 gfpMul(&e.y, &a.y, b) 159 return e 160 } 161 162 func (e *gfP2) Invert(a *gfP2) *gfP2 { 163 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 164 // ftp://136.206.11.249/pub/crypto/pairings.pdf 165 t1, t2, t3 := &gfP{}, &gfP{}, &gfP{} 166 gfpSqr(t1, &a.x, 1) 167 gfpDouble(t3, t1) 168 gfpSqr(t2, &a.y, 1) 169 gfpAdd(t3, t3, t2) 170 171 inv := &gfP{} 172 inv.Invert(t3) // inv = (2 * a.x ^ 2 + a.y ^ 2) ^ (-1) 173 174 gfpNeg(t1, &a.x) 175 176 gfpMul(&e.x, t1, inv) // x = - a.x * inv 177 gfpMul(&e.y, &a.y, inv) // y = a.y * inv 178 return e 179 } 180 181 func (e *gfP2) Exp(f *gfP2, power *big.Int) *gfP2 { 182 sum := (&gfP2{}).SetOne() 183 t := &gfP2{} 184 185 for i := power.BitLen() - 1; i >= 0; i-- { 186 t.Square(sum) 187 if power.Bit(i) != 0 { 188 sum.Mul(t, f) 189 } else { 190 sum.Set(t) 191 } 192 } 193 194 e.Set(sum) 195 return e 196 } 197 198 // (xu+y)^p = x * u^p + y 199 // 200 // = x * u * u^(p-1) + y 201 // = (-x)*u + y 202 // 203 // here u^(p-1) = -1 204 func (e *gfP2) Frobenius(a *gfP2) *gfP2 { 205 e.Conjugate(a) 206 return e 207 } 208 209 // Sqrt method is only required when we implement compressed format 210 // TODO: use addchain to improve performance for 3 exp operations. 211 func (ret *gfP2) Sqrt(a *gfP2) *gfP2 { 212 // Algorithm 10 https://eprint.iacr.org/2012/685.pdf 213 // TODO 214 ret.SetZero() 215 c := &twistGen.x 216 b, b2, bq := &gfP2{}, &gfP2{}, &gfP2{} 217 b = b.expPMinus1Over4(a) 218 b2.Mul(b, b) 219 bq = bq.expP(b) 220 221 t := &gfP2{} 222 x0 := &gfP{} 223 /* ignore sqrt existing check 224 a0 := &gfP2{} 225 a0.Exp(b2, p) 226 a0.Mul(a0, b2) 227 a0 = gfP2Decode(a0) 228 */ 229 t.Mul(bq, b) 230 if t.x.Equal(zero) == 1 && t.y.Equal(one) == 1 { 231 t.Mul(b2, a) 232 x0.Sqrt(&t.y) 233 t.MulScalar(bq, x0) 234 ret.Set(t) 235 } else { 236 d, e, f := &gfP2{}, &gfP2{}, &gfP2{} 237 d = d.expPMinus1Over2(c) 238 e.Mul(d, c) 239 f.Square(e) 240 e.Invert(e) 241 t.Mul(b2, a) 242 t.Mul(t, f) 243 x0.Sqrt(&t.y) 244 t.MulScalar(bq, x0) 245 t.Mul(t, e) 246 ret.Set(t) 247 } 248 return ret 249 } 250 251 // Select sets e to p1 if cond == 1, and to p2 if cond == 0. 252 func (e *gfP2) Select(p1, p2 *gfP2, cond int) *gfP2 { 253 e.x.Select(&p1.x, &p2.x, cond) 254 e.y.Select(&p1.y, &p2.y, cond) 255 return e 256 }