github.com/emmansun/gmsm@v0.29.1/sm9/bn256/bn_pair.go (about) 1 // Package bn256 defines/implements ShangMi(SM) sm9's curves and pairing. 2 package bn256 3 4 func lineFunctionAdd(r, p, rOut *twistPoint, q *curvePoint, r2, a, b, c *gfP2) { 5 // See the mixed addition algorithm from "Faster Computation of the 6 // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf 7 B := (&gfP2{}).Mul(&p.x, &r.t) // B = Xp * Zr^2 8 9 D := (&gfP2{}).Add(&p.y, &r.z) // D = Yp + Zr 10 D.Square(D).Sub(D, r2).Sub(D, &r.t).Mul(D, &r.t) // D = ((Yp + Zr)^2 - Zr^2 - Yp^2)*Zr^2 = 2Yp*Zr^3 11 12 H := (&gfP2{}).Sub(B, &r.x) // H = Xp * Zr^2 - Xr 13 I := (&gfP2{}).Square(H) // I = (Xp * Zr^2 - Xr)^2 = Xp^2*Zr^4 + Xr^2 - 2Xr*Xp*Zr^2 14 15 E := (&gfP2{}).Double(I) // E = 2*(Xp * Zr^2 - Xr)^2 16 E.Double(E) // E = 4*(Xp * Zr^2 - Xr)^2 17 18 J := (&gfP2{}).Mul(H, E) // J = 4*(Xp * Zr^2 - Xr)^3 19 20 L1 := (&gfP2{}).Sub(D, &r.y) // L1 = 2Yp*Zr^3 - Yr 21 L1.Sub(L1, &r.y) // L1 = 2Yp*Zr^3 - 2*Yr 22 23 V := (&gfP2{}).Mul(&r.x, E) // V = 4 * Xr * (Xp * Zr^2 - Xr)^2 24 25 rOut.x.Square(L1).Sub(&rOut.x, J).Sub(&rOut.x, V).Sub(&rOut.x, V) // rOut.x = L1^2 - J - 2V 26 27 rOut.z.Add(&r.z, H).Square(&rOut.z).Sub(&rOut.z, &r.t).Sub(&rOut.z, I) // rOut.z = (Zr + H)^2 - Zr^2 - I 28 29 t := (&gfP2{}).Sub(V, &rOut.x) // t = V - rOut.x 30 t.Mul(t, L1) // t = L1*(V-rOut.x) 31 t2 := (&gfP2{}).Mul(&r.y, J) 32 t2.Double(t2) // t2 = 2Yr * J 33 rOut.y.Sub(t, t2) // rOut.y = L1*(V-rOut.x) - 2Yr*J 34 35 rOut.t.Square(&rOut.z) 36 37 // t = (Yp + rOut.Z)^2 - Yp^2 - rOut.Z^2 = 2Yp*rOut.Z 38 t.Add(&p.y, &rOut.z).Square(t).Sub(t, r2).Sub(t, &rOut.t) 39 40 t2.Mul(L1, &p.x) 41 t2.Double(t2) // t2 = 2 L1 * Xp 42 a.Sub(t2, t) // a = 2 L1 * Xp - 2 Yp * rOut.z = 2 L1 * Xp - (Yp + rOut.Z)^2 + Yp^2 + rOut.Z^2 43 44 c.MulScalar(&rOut.z, &q.y) // c = rOut.z * Yq 45 c.Double(c) // c = 2 * rOut.z * Yq 46 47 b.Neg(L1) // b= -L1 48 b.MulScalar(b, &q.x).Double(b) // b = -2 * L1 * Xq 49 } 50 51 func lineFunctionDouble(r, rOut *twistPoint, q *curvePoint, a, b, c *gfP2) { 52 // See the doubling algorithm for a=0 from "Faster Computation of the 53 // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf 54 A := (&gfP2{}).Square(&r.x) 55 B := (&gfP2{}).Square(&r.y) 56 C := (&gfP2{}).Square(B) // C = Yr ^ 4 57 58 D := (&gfP2{}).Add(&r.x, B) 59 D.Square(D).Sub(D, A).Sub(D, C).Double(D) 60 61 E := (&gfP2{}).Double(A) // 62 E.Add(E, A) // E = 3 * Xr ^ 2 63 64 G := (&gfP2{}).Square(E) // G = 9 * Xr^4 65 66 rOut.x.Sub(G, D).Sub(&rOut.x, D) 67 68 rOut.z.Add(&r.y, &r.z).Square(&rOut.z).Sub(&rOut.z, B).Sub(&rOut.z, &r.t) // Z3 = (Yr + Zr)^2 - Yr^2 - Zr^2 = 2Yr*Zr 69 70 rOut.y.Sub(D, &rOut.x).Mul(&rOut.y, E) 71 t := (&gfP2{}).Double(C) // t = 2 * r.y ^ 4 72 t.Double(t).Double(t) // t = 8 * Yr ^ 4 73 rOut.y.Sub(&rOut.y, t) 74 75 rOut.t.Square(&rOut.z) 76 77 t.Mul(E, &r.t).Double(t) // t = 2(E * Tr) 78 b.Neg(t) // b = -2(E * Tr) 79 b.MulScalar(b, &q.x) // b = -2(E * Tr * Xq) 80 81 a.Add(&r.x, E) // a = Xr + E 82 a.Square(a).Sub(a, A).Sub(a, G) // a = (Xr + E) ^ 2 - A - G 83 t.Double(B).Double(t) // t = 4B 84 a.Sub(a, t) // a = (Xr + E) ^ 2 - A - G - 4B 85 86 c.Mul(&rOut.z, &r.t) // c = rOut.z * Tr 87 c.Double(c).MulScalar(c, &q.y) // c = 2 rOut.z * Tr * Yq 88 } 89 90 // (ret.z + ret.y*w + ret.x*w^2)* ((cv+a) + b*w^2) 91 func mulLine(ret *gfP12, a, b, c *gfP2) { 92 tz, t := &gfP4{}, &gfP4{} 93 tz.MulNC2(&ret.z, c, a) 94 t.MulScalar(&ret.y, b).MulV1(t) 95 tz.Add(tz, t) 96 97 t.MulNC2(&ret.y, c, a) 98 ret.y.MulScalar(&ret.x, b).MulV1(&ret.y) 99 ret.y.Add(&ret.y, t) 100 101 t.MulNC2(&ret.x, c, a) 102 ret.x.MulScalar(&ret.z, b) 103 ret.x.Add(&ret.x, t) 104 105 gfp4Copy(&ret.z, tz) 106 } 107 108 // R-ate Pairing G2 x G1 -> GT 109 // 110 // P is a point of order q in G1. Q(x,y) is a point of order q in G2. 111 // Note that Q is a point on the sextic twist of the curve over Fp^2, P(x,y) is a point on the 112 // curve over the base field Fp 113 func miller(q *twistPoint, p *curvePoint) *gfP12 { 114 ret := (&gfP12{}).SetOne() 115 116 aAffine := &twistPoint{} 117 aAffine.Set(q) 118 aAffine.MakeAffine() 119 120 minusA := &twistPoint{} 121 minusA.Neg(aAffine) 122 123 bAffine := &curvePoint{} 124 bAffine.Set(p) 125 bAffine.MakeAffine() 126 127 r := &twistPoint{} 128 r.Set(aAffine) 129 130 r2 := (&gfP2{}).Square(&aAffine.y) 131 132 a, b, c := &gfP2{}, &gfP2{}, &gfP2{} 133 newR := &twistPoint{} 134 var tmpR *twistPoint 135 for i := len(sixUPlus2NAF) - 1; i > 0; i-- { 136 lineFunctionDouble(r, newR, bAffine, a, b, c) 137 if i != len(sixUPlus2NAF)-1 { 138 ret.Square(ret) 139 } 140 mulLine(ret, a, b, c) 141 tmpR = r 142 r = newR 143 newR = tmpR 144 switch sixUPlus2NAF[i-1] { 145 case 1: 146 lineFunctionAdd(r, aAffine, newR, bAffine, r2, a, b, c) 147 case -1: 148 lineFunctionAdd(r, minusA, newR, bAffine, r2, a, b, c) 149 default: 150 continue 151 } 152 153 mulLine(ret, a, b, c) 154 tmpR = r 155 r = newR 156 newR = tmpR 157 } 158 159 // In order to calculate Q1 we have to convert q from the sextic twist 160 // to the full GF(p^12) group, apply the Frobenius there, and convert 161 // back. 162 // 163 // The twist isomorphism is (x', y') -> (x*β^(-1/3), y*β^(-1/2)). If we consider just 164 // x for a moment, then after applying the Frobenius, we have x̄*β^(-p/3) 165 // where x̄ is the conjugate of x. If we are going to apply the inverse 166 // isomorphism we need a value with a single coefficient of β^(-1/3) so we 167 // rewrite this as x̄*β^((-p+1)/3)*β^(-1/3). 168 // 169 // A similar argument can be made for the y value. 170 q1 := &twistPoint{} 171 q1.x.Conjugate(&aAffine.x) 172 q1.x.MulScalar(&q1.x, betaToNegPPlus1Over3) 173 q1.y.Conjugate(&aAffine.y) 174 q1.y.MulScalar(&q1.y, betaToNegPPlus1Over2) 175 q1.z.SetOne() 176 q1.t.SetOne() 177 178 minusQ2 := &twistPoint{} 179 minusQ2.x.Set(&aAffine.x) 180 minusQ2.x.MulScalar(&minusQ2.x, betaToNegP2Plus1Over3) 181 minusQ2.y.Neg(&aAffine.y) 182 minusQ2.y.MulScalar(&minusQ2.y, betaToNegP2Plus1Over2) 183 minusQ2.z.SetOne() 184 minusQ2.t.SetOne() 185 186 r2.Square(&q1.y) 187 lineFunctionAdd(r, q1, newR, bAffine, r2, a, b, c) 188 mulLine(ret, a, b, c) 189 tmpR = r 190 r = newR 191 newR = tmpR 192 193 r2.Square(&minusQ2.y) 194 lineFunctionAdd(r, minusQ2, newR, bAffine, r2, a, b, c) 195 mulLine(ret, a, b, c) 196 197 return ret 198 } 199 200 // finalExponentiation computes the (p¹²-1)/Order-th power of an element of 201 // GF(p¹²) to obtain an element of GT. https://eprint.iacr.org/2007/390.pdf 202 // http://cryptojedi.org/papers/dclxvi-20100714.pdf 203 func finalExponentiation(in *gfP12) *gfP12 { 204 // This is the p^6-Frobenius 205 t1 := (&gfP12{}).FrobeniusP6(in) 206 207 inv := (&gfP12{}).Invert(in) 208 t1.Mul(t1, inv) 209 210 t2 := inv.FrobeniusP2(t1) // reuse inv 211 t1.Mul(t1, t2) // t1 = in ^ ((p^6 - 1) * (p^2 + 1)), the first two parts of the exponentiation 212 213 fp := (&gfP12{}).Frobenius(t1) 214 fp2 := (&gfP12{}).FrobeniusP2(t1) 215 fp3 := (&gfP12{}).Frobenius(fp2) 216 217 y0 := &gfP12{} 218 y0.MulNC(fp, fp2).Mul(y0, fp3) // y0 = (t1^p) * (t1^(p^2)) * (t1^(p^3)) 219 220 // reuse fp, fp2, fp3 local variables 221 fu := fp.Cyclo6PowToU(t1) 222 fu2 := fp2.Cyclo6PowToU(fu) 223 fu3 := fp3.Cyclo6PowToU(fu2) 224 225 fu2p := (&gfP12{}).Frobenius(fu2) 226 fu3p := (&gfP12{}).Frobenius(fu3) 227 228 y1 := (&gfP12{}).Conjugate(t1) // y1 = 1 / t1 229 y2 := (&gfP12{}).FrobeniusP2(fu2) // y2 = (t1^(u^2))^(p^2) 230 y3 := (&gfP12{}).Frobenius(fu) // y3 = (t1^u)^p 231 y3.Conjugate(y3) // y3 = 1 / (t1^u)^p 232 y4 := (&gfP12{}).MulNC(fu, fu2p) // y4 = (t1^u) * ((t1^(u^2))^p) 233 y4.Conjugate(y4) // y4 = 1 / ((t1^u) * ((t1^(u^2))^p)) 234 y5 := fu2p.Conjugate(fu2) // y5 = 1 / t1^(u^2), reuse fu2p 235 y6 := (&gfP12{}).MulNC(fu3, fu3p) // y6 = t1^(u^3) * (t1^(u^3))^p 236 y6.Conjugate(y6) // y6 = 1 / (t1^(u^3) * (t1^(u^3))^p) 237 238 // https://eprint.iacr.org/2008/490.pdf 239 t0 := (&gfP12{}).Cyclo6SquareNC(y6) 240 t0.Mul(t0, y4).Mul(t0, y5) 241 t1.Mul(y3, y5).Mul(t1, t0) 242 t0.Mul(t0, y2) 243 t1.Cyclo6Square(t1).Mul(t1, t0).Cyclo6Square(t1) 244 t0.Mul(t1, y1) 245 t1.Mul(t1, y0) 246 t0.Cyclo6Square(t0).Mul(t0, t1) 247 248 return t0 249 } 250 251 func pairing(a *twistPoint, b *curvePoint) *gfP12 { 252 e := miller(a, b) 253 ret := finalExponentiation(e) 254 255 if a.IsInfinity() || b.IsInfinity() { 256 ret.SetOne() 257 } 258 return ret 259 }