1 package ff
2
3 import (
4 "crypto/subtle"
5 "fmt"
6 )
7
8
9 const Fp12Size = 2 * Fp6Size
10
11
12 type Fp12 [2]Fp6
13
14 func (z Fp12) String() string { return fmt.Sprintf("0: %v\n1: %v", z[0], z[1]) }
15 func (z *Fp12) SetOne() { z[0].SetOne(); z[1] = Fp6{} }
16 func (z Fp12) IsZero() int { return z.IsEqual(&Fp12{}) }
17 func (z Fp12) IsEqual(x *Fp12) int { return z[0].IsEqual(&x[0]) & z[1].IsEqual(&x[1]) }
18 func (z *Fp12) MulBeta() { t := z[0]; z[0].Sub(&z[0], &z[1]); z[1].Add(&t, &z[1]) }
19 func (z *Fp12) Frob(x *Fp12) { z[0].Frob(&x[0]); z[1].Frob(&x[1]); z[1].Mul(&z[1], &Fp6{frob12W1}) }
20 func (z *Fp12) Cjg() { z[1].Neg() }
21 func (z *Fp12) Neg() { z[0].Neg(); z[1].Neg() }
22 func (z *Fp12) Add(x, y *Fp12) { z[0].Add(&x[0], &y[0]); z[1].Add(&x[1], &y[1]) }
23 func (z *Fp12) Sub(x, y *Fp12) { z[0].Sub(&x[0], &y[0]); z[1].Sub(&x[1], &y[1]) }
24 func (z *Fp12) Mul(x, y *Fp12) {
25 var x0y0, x1y1, sx, sy, k Fp6
26 x0y0.Mul(&x[0], &y[0])
27 x1y1.Mul(&x[1], &y[1])
28 sx.Add(&x[0], &x[1])
29 sy.Add(&y[0], &y[1])
30 k.Mul(&sx, &sy)
31 z[1].Sub(&k, &x0y0)
32 z[1].Sub(&z[1], &x1y1)
33 x1y1.MulBeta()
34 z[0].Add(&x0y0, &x1y1)
35 }
36
37 func (z *Fp12) Sqr(x *Fp12) {
38 var x02, x12, k Fp6
39 x02.Sqr(&x[0])
40 x12.Sqr(&x[1])
41 x12.MulBeta()
42 k.Mul(&x[0], &x[1])
43 z[0].Add(&x02, &x12)
44 z[1].Add(&k, &k)
45 }
46
47 func (z *Fp12) Inv(x *Fp12) {
48 var x02, x12, den Fp6
49 x02.Sqr(&x[0])
50 x12.Sqr(&x[1])
51 x12.MulBeta()
52 den.Sub(&x02, &x12)
53 den.Inv(&den)
54 z[0].Mul(&x[0], &den)
55 z[1].Mul(&x[1], &den)
56 z[1].Neg()
57 }
58
59 func (z *Fp12) CMov(x, y *Fp12, b int) {
60 z[0].CMov(&x[0], &y[0], b)
61 z[1].CMov(&x[1], &y[1], b)
62 }
63
64
65 func (z *Fp12) Exp(x *Fp12, n []byte) {
66 zz := new(Fp12)
67 zz.SetOne()
68 T := new(Fp12)
69 var mults [16]Fp12
70 mults[0].SetOne()
71 mults[1] = *x
72 for i := 1; i < 8; i++ {
73 mults[2*i] = mults[i]
74 mults[2*i].Sqr(&mults[2*i])
75 mults[2*i+1].Mul(&mults[2*i], x)
76 }
77 N := 8 * len(n)
78 for i := 0; i < N; i += 4 {
79 zz.Sqr(zz)
80 zz.Sqr(zz)
81 zz.Sqr(zz)
82 zz.Sqr(zz)
83 idx := 0xf & (n[i/8] >> uint(4-i%8))
84 for j := 0; j < 16; j++ {
85 T.CMov(T, &mults[j], subtle.ConstantTimeByteEq(idx, uint8(j)))
86 }
87 zz.Mul(zz, T)
88 }
89 *z = *zz
90 }
91
92 func (z *Fp12) UnmarshalBinary(b []byte) error {
93 if len(b) < Fp12Size {
94 return errInputLength
95 }
96 return errFirst(
97 z[1].UnmarshalBinary(b[:Fp6Size]),
98 z[0].UnmarshalBinary(b[Fp6Size:2*Fp6Size]),
99 )
100 }
101
102 func (z Fp12) MarshalBinary() (b []byte, e error) {
103 var b0, b1 []byte
104 if b1, e = z[1].MarshalBinary(); e == nil {
105 if b0, e = z[0].MarshalBinary(); e == nil {
106 return append(b1, b0...), e
107 }
108 }
109 return
110 }
111
112
113
114
115
116 var frob12W1 = Fp2{
117 Fp{fpMont{
118 0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f,
119 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb,
120 }},
121 Fp{fpMont{
122 0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394,
123 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf,
124 }},
125 }
126
View as plain text