github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/cyclo6.go (about) 1 package ff 2 3 // Cyclo6 represents an element of the 6th cyclotomic group. 4 type Cyclo6 Fp12 5 6 func (z Cyclo6) String() string { return (Fp12)(z).String() } 7 func (z Cyclo6) IsEqual(x *Cyclo6) int { return (Fp12)(z).IsEqual((*Fp12)(x)) } 8 func (z Cyclo6) IsIdentity() int { i := &Fp12{}; i.SetOne(); return z.IsEqual((*Cyclo6)(i)) } 9 func (z *Cyclo6) Frob(x *Cyclo6) { (*Fp12)(z).Frob((*Fp12)(x)) } 10 func (z *Cyclo6) Mul(x, y *Cyclo6) { (*Fp12)(z).Mul((*Fp12)(x), (*Fp12)(y)) } 11 func (z *Cyclo6) Inv(x *Cyclo6) { *z = *x; z[1].Neg() } 12 func (z *Cyclo6) exp(x *Cyclo6, n []byte) { (*Fp12)(z).Exp((*Fp12)(x), n) } 13 func (z *Cyclo6) Sqr(x *Cyclo6) { 14 // Method of Granger-Scott. 15 // Page 7 of "Faster Squaring in the Cyclotomic Subgroup of Sixth Degree Extensions" 16 // https://www.iacr.org/archive/pkc2010/60560212/60560212.pdf 17 var xx, zz Fp12Cubic 18 xx.FromFp12((*Fp12)(x)) 19 20 a, b, c := &xx[0], &xx[1], &xx[2] 21 z0, z1, z2 := &zz[0], &zz[1], &zz[2] 22 23 var aa, bb, cc, tt Fp4 24 aa.Sqr(a) 25 bb.Sqr(b) 26 cc.Sqr(c) 27 cc.mulT(&cc) 28 29 z0.Add(&aa, &aa) 30 z0.Add(z0, &aa) 31 tt.Add(a, a) 32 tt.Cjg() 33 z0.Sub(z0, &tt) 34 35 z1.Add(&cc, &cc) 36 z1.Add(z1, &cc) 37 tt.Add(b, b) 38 tt.Cjg() 39 z1.Add(z1, &tt) 40 41 z2.Add(&bb, &bb) 42 z2.Add(z2, &bb) 43 tt.Add(c, c) 44 tt.Cjg() 45 z2.Sub(z2, &tt) 46 47 (*Fp12)(z).FromFp12Cubic(&zz) 48 } 49 50 // PowToX computes z = x^paramX, where paramX is the parameter of the BLS curve. 51 func (z *Cyclo6) PowToX(x *Cyclo6) { 52 t := new(Cyclo6) 53 *t = *x 54 const lenX = 64 55 for i := lenX - 2; i >= 0; i-- { 56 t.Sqr(t) 57 // paramX is -2 ^ 63 - 2 ^ 62 - 2 ^ 60 - 2 ^ 57 - 2 ^ 48 - 2 ^ 16 58 if (i == 62) || (i == 60) || (i == 57) || (i == 48) || (i == 16) { 59 t.Mul(t, x) 60 } 61 } 62 z.Inv(t) 63 } 64 65 // EasyExponentiation calculates g = f^(p^6-1)(p^2+1), where g becomes an 66 // element of the 6-th cyclotomic group. 67 func EasyExponentiation(g *Cyclo6, f *Fp12) { 68 var t0, t1, p Fp12 69 p.Frob(f) // p = f^(p) 70 p.Frob(&p) // p = f^(p^2) 71 t0.Mul(&p, f) // t0 = f^(p^2 + 1) 72 t1.Frob(&t0) // t1 = f^(p^2 + 1)*(p) 73 t1.Frob(&t1) // t1 = f^(p^2 + 1)*(p^2) 74 t1.Frob(&t1) // t1 = f^(p^2 + 1)*(p^3) 75 t1.Frob(&t1) // t1 = f^(p^2 + 1)*(p^4) 76 t1.Frob(&t1) // t1 = f^(p^2 + 1)*(p^5) 77 t1.Frob(&t1) // t1 = f^(p^2 + 1)*(p^6) 78 t0.Inv(&t0) // t0 = f^-(p^2 + 1) 79 t0.Mul(&t0, &t1) // t0 = f^(p^2 + 1)*(p^6 - 1) 80 81 *g = (Cyclo6)(t0) 82 } 83 84 // HardExponentiation calculates u = g^(Cy_6(p)/r), where u is a root of unity. 85 func HardExponentiation(u *URoot, g *Cyclo6) { 86 var t0, t1, _g, g3 Cyclo6 87 var c, a0, a1, a2, a3 Cyclo6 88 _g.Inv(g) // _g = g^-1 89 g3.Sqr(g) // g3 = g^2 90 g3.Mul(&g3, g) // g3 = g^3 91 t0.PowToX(g) // t0 = g^x 92 t0.Mul(&t0, &_g) // t0 = g^(x-1) 93 t1.PowToX(&t0) // t1 = g^(x-1)*x 94 t0.Inv(&t0) // t0 = g^-(x-1) 95 a3.Mul(&t1, &t0) // a3 = g^(x-1)*(x-1) 96 a2.Frob(&a3) // a2 = a3*p 97 a1.Frob(&a2) // a1 = a2*p = a3*p^2 98 t0.Inv(&a3) // t0 = -a3 99 a1.Mul(&a1, &t0) // a1 = a3*p^2-a3 100 a0.Frob(&a1) // a0 = a3*p^3-a3*p 101 a0.Mul(&a0, &g3) // a0 = a3*p^3-a3*p+3 102 103 c.PowToX(&a3) // c = g^(a3*x) 104 c.Mul(&c, &a2) // c = g^(a3*x+a2) 105 c.PowToX(&c) // c = g^(a3*x+a2)*x = g^(a3*x^2+a2*x) 106 c.Mul(&c, &a1) // c = g^(a3*x^2+a2*x+a1) 107 c.PowToX(&c) // c = g^(a3*x^2+a2*x+a1)*x = g^(a3*x^3+a2*x^2+a1*x) 108 c.Mul(&c, &a0) // c = g^(a3*x^3+a2*x^2+a1*x+a0) 109 110 *u = (URoot)(c) 111 }