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 )