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  }