github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/fp6.go (about)

     1  package ff
     2  
     3  import "fmt"
     4  
     5  // Fp6Size is the length in bytes of an Fp6 element.
     6  const Fp6Size = 3 * Fp2Size
     7  
     8  type Fp6 [3]Fp2
     9  
    10  func (z Fp6) String() string { return fmt.Sprintf("\n0: %v\n1: %v\n2: %v", z[0], z[1], z[2]) }
    11  func (z *Fp6) SetOne()       { z[0].SetOne(); z[1] = Fp2{}; z[2] = Fp2{} }
    12  func (z Fp6) IsZero() int    { return z.IsEqual(&Fp6{}) }
    13  func (z Fp6) IsEqual(x *Fp6) int {
    14  	return z[0].IsEqual(&x[0]) & z[1].IsEqual(&x[1]) & z[2].IsEqual(&x[2])
    15  }
    16  func (z *Fp6) Neg()          { z[0].Neg(); z[1].Neg(); z[2].Neg() }
    17  func (z *Fp6) Add(x, y *Fp6) { z[0].Add(&x[0], &y[0]); z[1].Add(&x[1], &y[1]); z[2].Add(&x[2], &y[2]) }
    18  func (z *Fp6) Sub(x, y *Fp6) { z[0].Sub(&x[0], &y[0]); z[1].Sub(&x[1], &y[1]); z[2].Sub(&x[2], &y[2]) }
    19  func (z *Fp6) MulBeta() {
    20  	t := z[2]
    21  	t.MulBeta()
    22  	z[2] = z[1]
    23  	z[1] = z[0]
    24  	z[0] = t
    25  }
    26  
    27  func (z *Fp6) Mul(x, y *Fp6) {
    28  	// https://ia.cr/2006/224 (Sec3.1)
    29  	//  z = x*y mod (v^3-B)
    30  	// | v^4 | v^3 ||  v^2  |  v^1  |  v^0  |
    31  	// |-----|-----||-------|-------|-------|
    32  	// |     |     ||  -c2  |  -c1  |  +c0  |
    33  	// |     | -c2 ||  +c1  |  -c0  |       |
    34  	// | +c2 | -c1 ||  -c0  |       |       |
    35  	// |     | +c5 ||  +c4  |  +c3  |       |
    36  	// |-----|-----||-------|-------|-------|
    37  	// |     |     ||       | B(+c2)| B(-c2)|
    38  	// |     |     ||       |       | B(-c1)|
    39  	// |     |     ||       |       | B(+c5)|
    40  
    41  	aL, aM, aH := &x[0], &x[1], &x[2]
    42  	bL, bM, bH := &y[0], &y[1], &y[2]
    43  	aLM, aLH, aMH := &Fp2{}, &Fp2{}, &Fp2{}
    44  	bLM, bLH, bMH := &Fp2{}, &Fp2{}, &Fp2{}
    45  	aLM.Add(aL, aM)
    46  	aLH.Add(aL, aH)
    47  	aMH.Add(aM, aH)
    48  	bLM.Add(bL, bM)
    49  	bLH.Add(bL, bH)
    50  	bMH.Add(bM, bH)
    51  
    52  	c0, c1, c2 := &Fp2{}, &Fp2{}, &Fp2{}
    53  	c5, c3, c4 := &z[0], &z[1], &z[2]
    54  	c0.Mul(aL, bL)
    55  	c1.Mul(aM, bM)
    56  	c2.Mul(aH, bH)
    57  	c3.Mul(aLM, bLM)
    58  	c4.Mul(aLH, bLH)
    59  	c5.Mul(aMH, bMH)
    60  
    61  	z[2].Add(c4, c1)    // c4+c1
    62  	z[2].Sub(&z[2], c0) // c4+c1-c0
    63  	z[2].Sub(&z[2], c2) // z2 = c4+c1-c0-c2
    64  	c2.MulBeta()        // Bc2
    65  	c2.Sub(c2, c0)      // Bc2-c0
    66  	z[1].Sub(c3, c1)    // c3-c1
    67  	z[1].Add(&z[1], c2) // z1 = Bc2-c0+c3-c1
    68  	z[0].Sub(c5, c1)    // c5-c1
    69  	z[0].MulBeta()      // B(c5-c1)
    70  	z[0].Sub(&z[0], c2) // z0 = B(c5-c1)-Bc2+c0 = B(c5-c1-c2)+c0
    71  }
    72  
    73  func (z *Fp6) Sqr(x *Fp6) {
    74  	//  z = x^2 mod (v^3-B)
    75  	// z0 = B(2x1*x2) + x0^2
    76  	// z1 = B(x2^2) + 2x0*x1
    77  	// z2 = 2x0*x2 + x1^2
    78  
    79  	aL, aM, aH := &x[0], &x[1], &x[2]
    80  	c0, c2, c4 := &z[0], &z[1], &z[2]
    81  	c3, c5, tt := &Fp2{}, &Fp2{}, &Fp2{}
    82  	tt.Add(aL, aH)
    83  	tt.Sub(tt, aM)
    84  
    85  	c3.Mul(aL, aM)
    86  	c5.Mul(aM, aH)
    87  	c0.Sqr(aL)
    88  	c2.Sqr(aH)
    89  	c4.Sqr(tt)
    90  
    91  	c5.Add(c5, c5)      // 2c5
    92  	c3.Add(c3, c3)      // 2c3
    93  	tt.Add(c3, c5)      // 2c3+2c5
    94  	z[2].Add(tt, c4)    // 2c3+2c5+c4
    95  	z[2].Sub(&z[2], c0) // 2c3+2c5+c4-c0
    96  	z[2].Sub(&z[2], c2) // z2 = 2c3+2c5+c4-c0-c2
    97  	c5.MulBeta()        // B(2c5)
    98  	z[0].Add(c5, c0)    // z0 = B(2c5)+c0
    99  	c2.MulBeta()        // B(c2)
   100  	z[1].Add(c2, c3)    // z1 = B(c2)+2c3
   101  }
   102  
   103  func (z *Fp6) Inv(x *Fp6) {
   104  	aL, aM, aH := &x[0], &x[1], &x[2]
   105  	c0, c1, c2 := &Fp2{}, &Fp2{}, &Fp2{}
   106  	t0, t1, t2 := &Fp2{}, &Fp2{}, &Fp2{}
   107  	c0.Sqr(aL)
   108  	c1.Sqr(aH)
   109  	c2.Sqr(aM)
   110  	t0.Mul(aM, aH)
   111  	t1.Mul(aL, aM)
   112  	t2.Mul(aL, aH)
   113  	t0.MulBeta()
   114  	c0.Sub(c0, t0) // c0 = aL^2 - B(aM*AH)
   115  	c1.MulBeta()
   116  	c1.Sub(c1, t1) // c1 = B(aH^2) - aL*AM
   117  	c2.Sub(c2, t2) // c1 = aM^2 - aL*AH
   118  
   119  	t0.Mul(aM, c2)
   120  	t1.Mul(aH, c1)
   121  	t2.Mul(aL, c0)
   122  	t0.Add(t0, t1)
   123  	t0.MulBeta()
   124  	t0.Add(t0, t2)
   125  	t0.Inv(t0)       // den = B(aL*c2 + aM*c1) + aLc0
   126  	z[0].Mul(c0, t0) // z0 = c0/den
   127  	z[1].Mul(c1, t0) // z1 = c1/den
   128  	z[2].Mul(c2, t0) // z2 = c2/den
   129  }
   130  
   131  func (z *Fp6) Frob(x *Fp6) {
   132  	z[0].Frob(&x[0])
   133  	z[1].Frob(&x[1])
   134  	z[2].Frob(&x[2])
   135  	z[1].Mul(&z[1], &Fp2{Fp{}, frob6V1})
   136  	z[2].Mul(&z[2], &Fp2{frob6V2, Fp{}})
   137  }
   138  
   139  func (z *Fp6) CMov(x, y *Fp6, b int) {
   140  	z[0].CMov(&x[0], &y[0], b)
   141  	z[1].CMov(&x[1], &y[1], b)
   142  	z[2].CMov(&x[2], &y[2], b)
   143  }
   144  
   145  func (z Fp6) MarshalBinary() (b []byte, e error) {
   146  	var b0, b1, b2 []byte
   147  	if b2, e = z[2].MarshalBinary(); e == nil {
   148  		if b1, e = z[1].MarshalBinary(); e == nil {
   149  			if b0, e = z[0].MarshalBinary(); e == nil {
   150  				return append(append(b2, b1...), b0...), e
   151  			}
   152  		}
   153  	}
   154  	return
   155  }
   156  
   157  func (z *Fp6) UnmarshalBinary(b []byte) error {
   158  	if len(b) < Fp6Size {
   159  		return errInputLength
   160  	}
   161  	return errFirst(
   162  		z[2].UnmarshalBinary(b[0*Fp2Size:1*Fp2Size]),
   163  		z[1].UnmarshalBinary(b[1*Fp2Size:2*Fp2Size]),
   164  		z[0].UnmarshalBinary(b[2*Fp2Size:3*Fp2Size]),
   165  	)
   166  }
   167  
   168  var (
   169  	// frob6V1 is toMont(v) = 2**384 * v mod fpPrime, where
   170  	// v = 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac
   171  	frob6V1 = Fp{fpMont{
   172  		0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95,
   173  		0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741,
   174  	}}
   175  
   176  	// frob6V2 is toMont(v) = 2**384 * v mod fpPrime, where
   177  	// v = 0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad
   178  	frob6V2 = Fp{fpMont{
   179  		0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c,
   180  		0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a,
   181  	}}
   182  )