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  }