github.com/bloxroute-labs/bor@v0.1.4/crypto/bn256/cloudflare/gfp6.go (about)

     1  package bn256
     2  
     3  // For details of the algorithms used, see "Multiplication and Squaring on
     4  // Pairing-Friendly Fields, Devegili et al.
     5  // http://eprint.iacr.org/2006/471.pdf.
     6  
     7  // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
     8  // and ξ=i+9.
     9  type gfP6 struct {
    10  	x, y, z gfP2 // value is xτ² + yτ + z
    11  }
    12  
    13  func (e *gfP6) String() string {
    14  	return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")"
    15  }
    16  
    17  func (e *gfP6) Set(a *gfP6) *gfP6 {
    18  	e.x.Set(&a.x)
    19  	e.y.Set(&a.y)
    20  	e.z.Set(&a.z)
    21  	return e
    22  }
    23  
    24  func (e *gfP6) SetZero() *gfP6 {
    25  	e.x.SetZero()
    26  	e.y.SetZero()
    27  	e.z.SetZero()
    28  	return e
    29  }
    30  
    31  func (e *gfP6) SetOne() *gfP6 {
    32  	e.x.SetZero()
    33  	e.y.SetZero()
    34  	e.z.SetOne()
    35  	return e
    36  }
    37  
    38  func (e *gfP6) IsZero() bool {
    39  	return e.x.IsZero() && e.y.IsZero() && e.z.IsZero()
    40  }
    41  
    42  func (e *gfP6) IsOne() bool {
    43  	return e.x.IsZero() && e.y.IsZero() && e.z.IsOne()
    44  }
    45  
    46  func (e *gfP6) Neg(a *gfP6) *gfP6 {
    47  	e.x.Neg(&a.x)
    48  	e.y.Neg(&a.y)
    49  	e.z.Neg(&a.z)
    50  	return e
    51  }
    52  
    53  func (e *gfP6) Frobenius(a *gfP6) *gfP6 {
    54  	e.x.Conjugate(&a.x)
    55  	e.y.Conjugate(&a.y)
    56  	e.z.Conjugate(&a.z)
    57  
    58  	e.x.Mul(&e.x, xiTo2PMinus2Over3)
    59  	e.y.Mul(&e.y, xiToPMinus1Over3)
    60  	return e
    61  }
    62  
    63  // FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
    64  func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 {
    65  	// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
    66  	e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3)
    67  	// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
    68  	e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3)
    69  	e.z.Set(&a.z)
    70  	return e
    71  }
    72  
    73  func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 {
    74  	e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3)
    75  	e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3)
    76  	e.z.Set(&a.z)
    77  	return e
    78  }
    79  
    80  func (e *gfP6) Add(a, b *gfP6) *gfP6 {
    81  	e.x.Add(&a.x, &b.x)
    82  	e.y.Add(&a.y, &b.y)
    83  	e.z.Add(&a.z, &b.z)
    84  	return e
    85  }
    86  
    87  func (e *gfP6) Sub(a, b *gfP6) *gfP6 {
    88  	e.x.Sub(&a.x, &b.x)
    89  	e.y.Sub(&a.y, &b.y)
    90  	e.z.Sub(&a.z, &b.z)
    91  	return e
    92  }
    93  
    94  func (e *gfP6) Mul(a, b *gfP6) *gfP6 {
    95  	// "Multiplication and Squaring on Pairing-Friendly Fields"
    96  	// Section 4, Karatsuba method.
    97  	// http://eprint.iacr.org/2006/471.pdf
    98  	v0 := (&gfP2{}).Mul(&a.z, &b.z)
    99  	v1 := (&gfP2{}).Mul(&a.y, &b.y)
   100  	v2 := (&gfP2{}).Mul(&a.x, &b.x)
   101  
   102  	t0 := (&gfP2{}).Add(&a.x, &a.y)
   103  	t1 := (&gfP2{}).Add(&b.x, &b.y)
   104  	tz := (&gfP2{}).Mul(t0, t1)
   105  	tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0)
   106  
   107  	t0.Add(&a.y, &a.z)
   108  	t1.Add(&b.y, &b.z)
   109  	ty := (&gfP2{}).Mul(t0, t1)
   110  	t0.MulXi(v2)
   111  	ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0)
   112  
   113  	t0.Add(&a.x, &a.z)
   114  	t1.Add(&b.x, &b.z)
   115  	tx := (&gfP2{}).Mul(t0, t1)
   116  	tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2)
   117  
   118  	e.x.Set(tx)
   119  	e.y.Set(ty)
   120  	e.z.Set(tz)
   121  	return e
   122  }
   123  
   124  func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 {
   125  	e.x.Mul(&a.x, b)
   126  	e.y.Mul(&a.y, b)
   127  	e.z.Mul(&a.z, b)
   128  	return e
   129  }
   130  
   131  func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 {
   132  	e.x.MulScalar(&a.x, b)
   133  	e.y.MulScalar(&a.y, b)
   134  	e.z.MulScalar(&a.z, b)
   135  	return e
   136  }
   137  
   138  // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
   139  func (e *gfP6) MulTau(a *gfP6) *gfP6 {
   140  	tz := (&gfP2{}).MulXi(&a.x)
   141  	ty := (&gfP2{}).Set(&a.y)
   142  
   143  	e.y.Set(&a.z)
   144  	e.x.Set(ty)
   145  	e.z.Set(tz)
   146  	return e
   147  }
   148  
   149  func (e *gfP6) Square(a *gfP6) *gfP6 {
   150  	v0 := (&gfP2{}).Square(&a.z)
   151  	v1 := (&gfP2{}).Square(&a.y)
   152  	v2 := (&gfP2{}).Square(&a.x)
   153  
   154  	c0 := (&gfP2{}).Add(&a.x, &a.y)
   155  	c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0)
   156  
   157  	c1 := (&gfP2{}).Add(&a.y, &a.z)
   158  	c1.Square(c1).Sub(c1, v0).Sub(c1, v1)
   159  	xiV2 := (&gfP2{}).MulXi(v2)
   160  	c1.Add(c1, xiV2)
   161  
   162  	c2 := (&gfP2{}).Add(&a.x, &a.z)
   163  	c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2)
   164  
   165  	e.x.Set(c2)
   166  	e.y.Set(c1)
   167  	e.z.Set(c0)
   168  	return e
   169  }
   170  
   171  func (e *gfP6) Invert(a *gfP6) *gfP6 {
   172  	// See "Implementing cryptographic pairings", M. Scott, section 3.2.
   173  	// ftp://136.206.11.249/pub/crypto/pairings.pdf
   174  
   175  	// Here we can give a short explanation of how it works: let j be a cubic root of
   176  	// unity in GF(p²) so that 1+j+j²=0.
   177  	// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
   178  	// = (xτ² + yτ + z)(Cτ²+Bτ+A)
   179  	// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
   180  	//
   181  	// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
   182  	// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
   183  	//
   184  	// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
   185  	t1 := (&gfP2{}).Mul(&a.x, &a.y)
   186  	t1.MulXi(t1)
   187  
   188  	A := (&gfP2{}).Square(&a.z)
   189  	A.Sub(A, t1)
   190  
   191  	B := (&gfP2{}).Square(&a.x)
   192  	B.MulXi(B)
   193  	t1.Mul(&a.y, &a.z)
   194  	B.Sub(B, t1)
   195  
   196  	C := (&gfP2{}).Square(&a.y)
   197  	t1.Mul(&a.x, &a.z)
   198  	C.Sub(C, t1)
   199  
   200  	F := (&gfP2{}).Mul(C, &a.y)
   201  	F.MulXi(F)
   202  	t1.Mul(A, &a.z)
   203  	F.Add(F, t1)
   204  	t1.Mul(B, &a.x).MulXi(t1)
   205  	F.Add(F, t1)
   206  
   207  	F.Invert(F)
   208  
   209  	e.x.Mul(C, F)
   210  	e.y.Mul(B, F)
   211  	e.z.Mul(A, F)
   212  	return e
   213  }