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  }