...

Source file src/github.com/cloudflare/circl/ecc/bls12381/pair.go

Documentation: github.com/cloudflare/circl/ecc/bls12381

     1  package bls12381
     2  
     3  import "github.com/cloudflare/circl/ecc/bls12381/ff"
     4  
     5  // Pair calculates the ate-pairing of P and Q.
     6  func Pair(P *G1, Q *G2) *Gt {
     7  	P.toAffine()
     8  	mi := &ff.Fp12{}
     9  	miller(mi, P, Q)
    10  	e := &Gt{}
    11  	finalExp(e, mi)
    12  	return e
    13  }
    14  
    15  func miller(f *ff.Fp12, P *G1, Q *G2) {
    16  	g := &ff.LineValue{}
    17  	acc := &ff.Fp12Cubic{}
    18  	acc.SetOne()
    19  	T := &G2{}
    20  	*T = *Q
    21  	l := &line{}
    22  	const lenX = 64
    23  	for i := lenX - 2; i >= 0; i-- {
    24  		acc.Sqr(acc)
    25  		doubleAndLine(T, l)
    26  		evalLine(g, l, P)
    27  		acc.MulLine(acc, g)
    28  		// paramX is -2 ^ 63 - 2 ^ 62 - 2 ^ 60 - 2 ^ 57 - 2 ^ 48 - 2 ^ 16
    29  		if (i == 62) || (i == 60) || (i == 57) || (i == 48) || (i == 16) {
    30  			addAndLine(T, T, Q, l)
    31  			evalLine(g, l, P)
    32  			acc.MulLine(acc, g)
    33  		}
    34  	}
    35  	f.FromFp12Alt(acc)
    36  	f.Cjg() // inverts f as paramX is negative.
    37  }
    38  
    39  // line contains the coefficients of a sparse element of Fp12.
    40  // Evaluating the line on P' = (xP',yP') results in
    41  //
    42  //	f = evalLine(P') = l[0]*xP' + l[1]*yP' + l[2] \in Fp12.
    43  type line [3]ff.Fp2
    44  
    45  // evalLine updates f = f * line(P'), where f lives in Fp12 = Fp6[w]/(w^2-v)
    46  // and P' is the image of P on the twist curve.
    47  func evalLine(f *ff.LineValue, l *line, P *G1) {
    48  	// Send P \in E to the twist
    49  	//     E    -->        E'
    50  	//  (xP,yP) |-> (xP*w^2,yP*w^3) = (xP',yP')
    51  	//
    52  	// f = line(P') = l[0]*xP' + l[1]*yP' + l[2] \in Fp12.
    53  	//              = l[0]*xP*w^2 + l[1]*yP*w^3 + l[2] \in Fp12.
    54  
    55  	// First perform the products: l[0]*xP and l[1]*yP \in Fp2.
    56  	var xP, yP ff.Fp2
    57  	xP[0] = P.x
    58  	yP[0] = P.y
    59  	f[1].Mul(&l[0], &xP)
    60  	f[2].Mul(&l[1], &yP)
    61  	f[0] = l[2]
    62  
    63  	if f.IsZero() == 1 {
    64  		f.SetOne()
    65  	}
    66  }
    67  
    68  func finalExp(g *Gt, f *ff.Fp12) {
    69  	c := &ff.Cyclo6{}
    70  	ff.EasyExponentiation(c, f)
    71  	ff.HardExponentiation(&g.i, c)
    72  }
    73  
    74  // ProdPair calculates the product of pairings, i.e., \Prod_i pair(Pi,Qi)^ni.
    75  func ProdPair(P []*G1, Q []*G2, n []*Scalar) *Gt {
    76  	if len(P) != len(Q) || len(P) != len(n) {
    77  		panic("mismatch length of inputs")
    78  	}
    79  
    80  	ei := new(ff.Fp12)
    81  	mi := new(ff.Fp12)
    82  	out := new(ff.Fp12)
    83  	out.SetOne()
    84  
    85  	affinize(P)
    86  	for i := range P {
    87  		miller(mi, P[i], Q[i])
    88  		nb, _ := n[i].MarshalBinary()
    89  		ei.Exp(mi, nb)
    90  		out.Mul(out, ei)
    91  	}
    92  
    93  	e := &Gt{}
    94  	finalExp(e, out)
    95  	return e
    96  }
    97  
    98  // ProdPairFrac computes the product e(P, Q)^sign where sign is 1 or -1
    99  func ProdPairFrac(P []*G1, Q []*G2, signs []int) *Gt {
   100  	if len(P) != len(Q) || len(P) != len(signs) {
   101  		panic("mismatch length of inputs")
   102  	}
   103  
   104  	mi := new(ff.Fp12)
   105  	out := new(ff.Fp12)
   106  	out.SetOne()
   107  
   108  	affinize(P)
   109  	for i := range P {
   110  		g := *P[i]
   111  		if signs[i] == -1 {
   112  			g.Neg()
   113  		}
   114  		miller(mi, &g, Q[i])
   115  		out.Mul(mi, out)
   116  	}
   117  
   118  	e := &Gt{}
   119  	finalExp(e, out)
   120  	return e
   121  }
   122  

View as plain text