github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp4.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  // gfP4 implements the field of size p^4 as a quadratic extension of gfP2
    11  // where v²=ξ and ξ=u.
    12  type gfP4 struct {
    13  	x, y gfP2 // value is xv+y.
    14  }
    15  
    16  func gfP4Decode(in *gfP4) *gfP4 {
    17  	out := &gfP4{}
    18  	out.x = *gfP2Decode(&in.x)
    19  	out.y = *gfP2Decode(&in.y)
    20  	return out
    21  }
    22  
    23  func (e *gfP4) String() string {
    24  	return "(" + e.x.String() + ", " + e.y.String() + ")"
    25  }
    26  
    27  func (e *gfP4) Set(a *gfP4) *gfP4 {
    28  	gfp4Copy(e, a)
    29  	return e
    30  }
    31  
    32  func (e *gfP4) SetZero() *gfP4 {
    33  	e.x.SetZero()
    34  	e.y.SetZero()
    35  	return e
    36  }
    37  
    38  func (e *gfP4) SetOne() *gfP4 {
    39  	e.x.SetZero()
    40  	e.y.SetOne()
    41  	return e
    42  }
    43  
    44  func (e *gfP4) SetV() *gfP4 {
    45  	e.x.SetOne()
    46  	e.y.SetZero()
    47  	return e
    48  }
    49  
    50  func (e *gfP4) IsZero() bool {
    51  	return e.x.IsZero() && e.y.IsZero()
    52  }
    53  
    54  func (e *gfP4) IsOne() bool {
    55  	return e.x.IsZero() && e.y.IsOne()
    56  }
    57  
    58  func (e *gfP4) Conjugate(a *gfP4) *gfP4 {
    59  	e.y.Set(&a.y)
    60  	e.x.Neg(&a.x)
    61  	return e
    62  }
    63  
    64  func (e *gfP4) Neg(a *gfP4) *gfP4 {
    65  	e.x.Neg(&a.x)
    66  	e.y.Neg(&a.y)
    67  	return e
    68  }
    69  
    70  func (e *gfP4) Add(a, b *gfP4) *gfP4 {
    71  	e.x.Add(&a.x, &b.x)
    72  	e.y.Add(&a.y, &b.y)
    73  	return e
    74  }
    75  
    76  func (e *gfP4) Double(a *gfP4) *gfP4 {
    77  	e.x.Double(&a.x)
    78  	e.y.Double(&a.y)
    79  	return e
    80  }
    81  
    82  func (e *gfP4) Triple(a *gfP4) *gfP4 {
    83  	e.x.Triple(&a.x)
    84  	e.y.Triple(&a.y)
    85  	return e
    86  }
    87  
    88  func (e *gfP4) Sub(a, b *gfP4) *gfP4 {
    89  	e.x.Sub(&a.x, &b.x)
    90  	e.y.Sub(&a.y, &b.y)
    91  	return e
    92  }
    93  
    94  func (e *gfP4) MulScalar(a *gfP4, b *gfP2) *gfP4 {
    95  	e.x.Mul(&a.x, b)
    96  	e.y.Mul(&a.y, b)
    97  	return e
    98  }
    99  
   100  func (e *gfP4) MulGFP(a *gfP4, b *gfP) *gfP4 {
   101  	e.x.MulScalar(&a.x, b)
   102  	e.y.MulScalar(&a.y, b)
   103  	return e
   104  }
   105  
   106  func (e *gfP4) Mul(a, b *gfP4) *gfP4 {
   107  	tmp := &gfP4{}
   108  	tmp.MulNC(a, b)
   109  	gfp4Copy(e, tmp)
   110  	return e
   111  }
   112  
   113  // Mul without value copy, will use e directly, so e can't be same as a and b.
   114  func (e *gfP4) MulNC(a, b *gfP4) *gfP4 {
   115  	// "Multiplication and Squaring on Pairing-Friendly Fields"
   116  	// Section 4, Karatsuba method.
   117  	// http://eprint.iacr.org/2006/471.pdf
   118  	//(a0+a1*v)(b0+b1*v)=c0+c1*v, where
   119  	//c0 = a0*b0 +a1*b1*u
   120  	//c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0
   121  	tx := &e.x
   122  	ty := &e.y
   123  	v0, v1 := &gfP2{}, &gfP2{}
   124  	v0.Mul(&a.y, &b.y)
   125  	v1.Mul(&a.x, &b.x)
   126  
   127  	tx.Add(&a.x, &a.y)
   128  	ty.Add(&b.x, &b.y)
   129  	tx.Mul(tx, ty)
   130  	tx.Sub(tx, v0)
   131  	tx.Sub(tx, v1)
   132  
   133  	ty.MulU1(v1)
   134  	ty.Add(ty, v0)
   135  
   136  	return e
   137  }
   138  
   139  // MulNC2 muls a with (xv+y), this method is used in mulLine function
   140  // to avoid gfP4 instance construction. e can't be same as a.
   141  func (e *gfP4) MulNC2(a *gfP4, x, y *gfP2) *gfP4 {
   142  	// "Multiplication and Squaring on Pairing-Friendly Fields"
   143  	// Section 4, Karatsuba method.
   144  	// http://eprint.iacr.org/2006/471.pdf
   145  	//(a0+a1*v)(b0+b1*v)=c0+c1*v, where
   146  	//c0 = a0*b0 +a1*b1*u
   147  	//c1 = (a0 + a1)(b0 + b1) - a0*b0 - a1*b1 = a0*b1 + a1*b0
   148  	tx := &e.x
   149  	ty := &e.y
   150  	v0, v1 := &gfP2{}, &gfP2{}
   151  	v0.Mul(&a.y, y)
   152  	v1.Mul(&a.x, x)
   153  
   154  	tx.Add(&a.x, &a.y)
   155  	ty.Add(x, y)
   156  	tx.Mul(tx, ty)
   157  	tx.Sub(tx, v0)
   158  	tx.Sub(tx, v1)
   159  
   160  	ty.MulU1(v1)
   161  	ty.Add(ty, v0)
   162  
   163  	return e
   164  }
   165  
   166  // MulV: a * b * v
   167  // (a0+a1*v)(b0+b1*v)*v=c0+c1*v, where
   168  // (a0*b0 + a0*b1v + a1*b0*v + a1*b1*u)*v
   169  // a0*b0*v + a0*b1*u + a1*b0*u + a1*b1*u*v
   170  // c0 = a0*b1*u + a1*b0*u
   171  // c1 = a0*b0 + a1*b1*u
   172  func (e *gfP4) MulV(a, b *gfP4) *gfP4 {
   173  	tmp := &gfP4{}
   174  	tmp.MulVNC(a, b)
   175  	gfp4Copy(e, tmp)
   176  	return e
   177  }
   178  
   179  // MulV without value copy, will use e directly, so e can't be same as a and b.
   180  func (e *gfP4) MulVNC(a, b *gfP4) *gfP4 {
   181  	tx := &e.x
   182  	ty := &e.y
   183  	v0, v1 := &gfP2{}, &gfP2{}
   184  	v0.Mul(&a.y, &b.y)
   185  	v1.Mul(&a.x, &b.x)
   186  
   187  	tx.Add(&a.x, &a.y)
   188  	ty.Add(&b.x, &b.y)
   189  	ty.Mul(tx, ty)
   190  	ty.Sub(ty, v0)
   191  	ty.Sub(ty, v1)
   192  	ty.MulU1(ty)
   193  
   194  	tx.MulU1(v1)
   195  	tx.Add(tx, v0)
   196  
   197  	return e
   198  }
   199  
   200  // MulV1: a * v
   201  // (a0+a1*v)*v=c0+c1*v, where
   202  // c0 = a1*u
   203  // c1 = a0
   204  func (e *gfP4) MulV1(a *gfP4) *gfP4 {
   205  	tx := &gfP2{}
   206  	gfp2Copy(tx, &a.y)
   207  
   208  	e.y.MulU1(&a.x)
   209  	gfp2Copy(&e.x, tx)
   210  	return e
   211  }
   212  
   213  func (e *gfP4) Square(a *gfP4) *gfP4 {
   214  	// Complex squaring algorithm:
   215  	// (xv+y)² = (x^2*u + y^2) + 2*x*y*v
   216  	tmp := &gfP4{}
   217  	tmp.SquareNC(a)
   218  	gfp4Copy(e, tmp)
   219  	return e
   220  }
   221  
   222  // Square without value copy, will use e directly, so e can't be same as a.
   223  func (e *gfP4) SquareNC(a *gfP4) *gfP4 {
   224  	// Complex squaring algorithm:
   225  	// (xv+y)² = (x^2*u + y^2) + 2*x*y*v
   226  	// = (xu + y)(x + y) -xy(1+u) + 2xy*v
   227  	tx := &e.x
   228  	ty := &e.y
   229  
   230  	tx.SquareU(&a.x)
   231  	ty.Square(&a.y)
   232  	ty.Add(tx, ty)
   233  
   234  	tx.Mul(&a.x, &a.y)
   235  	tx.Add(tx, tx)
   236  
   237  	return e
   238  }
   239  
   240  // SquareV without value copy, will use e directly, so e can't be same as a.
   241  // SquareV: (a^2) * v
   242  // v*(xv+y)² = (x^2*u + y^2)v + 2*x*y*u
   243  func (e *gfP4) SquareV(a *gfP4) *gfP4 {
   244  	tmp := &gfP4{}
   245  	tmp.SquareVNC(a)
   246  	gfp4Copy(e, tmp)
   247  	return e
   248  }
   249  
   250  func (e *gfP4) SquareVNC(a *gfP4) *gfP4 {
   251  	tx := &e.x
   252  	ty := &e.y
   253  	tx.SquareU(&a.x)
   254  	ty.Square(&a.y)
   255  	tx.Add(tx, ty)
   256  
   257  	ty.MulU(&a.x, &a.y)
   258  	ty.Add(ty, ty)
   259  
   260  	return e
   261  }
   262  
   263  func (e *gfP4) Invert(a *gfP4) *gfP4 {
   264  	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
   265  	// ftp://136.206.11.249/pub/crypto/pairings.pdf
   266  	tmp := &gfP4{}
   267  	t2 := &tmp.x
   268  	t1 := &tmp.y
   269  
   270  	t3 := &gfP2{}
   271  
   272  	t3.SquareU(&a.x)
   273  	t1.Square(&a.y)
   274  	t3.Sub(t3, t1)
   275  	t3.Invert(t3)
   276  
   277  	t1.Mul(&a.y, t3)
   278  	t1.Neg(t1)
   279  
   280  	t2.Mul(&a.x, t3)
   281  
   282  	gfp4Copy(e, tmp)
   283  	return e
   284  }
   285  
   286  func (e *gfP4) Exp(f *gfP4, power *big.Int) *gfP4 {
   287  	sum := (&gfP4{}).SetOne()
   288  	t := &gfP4{}
   289  
   290  	for i := power.BitLen() - 1; i >= 0; i-- {
   291  		t.Square(sum)
   292  		if power.Bit(i) != 0 {
   293  			sum.Mul(t, f)
   294  		} else {
   295  			sum.Set(t)
   296  		}
   297  	}
   298  
   299  	e.Set(sum)
   300  	return e
   301  }
   302  
   303  //	(y+x*v)^p
   304  //
   305  // = y^p + x^p*v^p
   306  // = f(y) + f(x) * v^p
   307  // = f(y) + f(x) * v * v^(p-1)
   308  func (e *gfP4) Frobenius(a *gfP4) *gfP4 {
   309  	tmp := &gfP4{}
   310  	x := &tmp.x
   311  	y := &tmp.y
   312  
   313  	x.Conjugate(&a.x)
   314  	y.Conjugate(&a.y)
   315  	x.MulScalar(x, vToPMinus1)
   316  
   317  	gfp4Copy(e, tmp)
   318  
   319  	return e
   320  }
   321  
   322  //	(y+x*v)^(p^2)
   323  //
   324  // y + x*v * v^(p^2-1)
   325  func (e *gfP4) FrobeniusP2(a *gfP4) *gfP4 {
   326  	e.Conjugate(a)
   327  	return e
   328  }
   329  
   330  //	(y+x*v)^(p^3)
   331  //
   332  // = ((y+x*v)^p)^(p^2)
   333  func (e *gfP4) FrobeniusP3(a *gfP4) *gfP4 {
   334  	tmp := &gfP4{}
   335  	x := &tmp.x
   336  	y := &tmp.y
   337  	x.Conjugate(&a.x)
   338  	y.Conjugate(&a.y)
   339  	x.MulScalar(x, vToPMinus1)
   340  	x.Neg(x)
   341  
   342  	gfp4Copy(e, tmp)
   343  
   344  	return e
   345  }
   346  
   347  // Select sets q to p1 if cond == 1, and to p2 if cond == 0.
   348  func (q *gfP4) Select(p1, p2 *gfP4, cond int) *gfP4 {
   349  	q.x.Select(&p1.x, &p2.x, cond)
   350  	q.y.Select(&p1.y, &p2.y, cond)
   351  	return q
   352  }