Coverage Summary for Class: Fp6 (co.rsk.crypto.altbn128java)
Class |
Class, %
|
Method, %
|
Line, %
|
Fp6 |
0%
(0/1)
|
0%
(0/19)
|
0%
(0/77)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2019 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package co.rsk.crypto.altbn128java;
21
22 import java.math.BigInteger;
23 import java.util.Objects;
24
25 /**
26 * Arithmetic in Fp_6 <br/>
27 * <br/>
28 *
29 * "p" equals 21888242871839275222246405745257275088696311157297823662689037894645226208583, <br/>
30 * elements of Fp_6 are represented with 3 elements of {@link Fp2} <br/>
31 * <br/>
32 *
33 * Field arithmetic is ported from <a href="https://github.com/scipr-lab/libff/blob/master/libff/algebra/fields/fp6_3over2.tcc">libff</a>
34 *
35 * @author Mikhail Kalinin
36 * @since 05.09.2017
37 */
38 class Fp6 implements Field<Fp6> {
39
40 public static final Fp6 ZERO = new Fp6(Fp2.ZERO, Fp2.ZERO, Fp2.ZERO);
41 public static final Fp6 _1 = new Fp6(Fp2._1, Fp2.ZERO, Fp2.ZERO);
42 public static final Fp2 NON_RESIDUE = new Fp2(BigInteger.valueOf(9), BigInteger.ONE);
43
44 private Fp2 a;
45
46 public Fp2 a() {
47 return a;
48 }
49
50 public Fp2 b() {
51 return b;
52 }
53
54 public Fp2 c() {
55 return c;
56 }
57
58 private Fp2 b;
59 private Fp2 c;
60
61 Fp6(Fp2 a, Fp2 b, Fp2 c) {
62 this.a = a;
63 this.b = b;
64 this.c = c;
65 }
66
67 @Override
68 public Fp6 squared() {
69
70 Fp2 s0 = a.squared();
71 Fp2 ab = a.mul(b);
72 Fp2 s1 = ab.dbl();
73 Fp2 s2 = a.sub(b).add(c).squared();
74 Fp2 bc = b.mul(c);
75 Fp2 s3 = bc.dbl();
76 Fp2 s4 = c.squared();
77
78 Fp2 ra = s0.add(s3.mulByNonResidue());
79 Fp2 rb = s1.add(s4.mulByNonResidue());
80 Fp2 rc = s1.add(s2).add(s3).sub(s0).sub(s4);
81
82 return new Fp6(ra, rb, rc);
83 }
84
85 @Override
86 public Fp6 dbl() {
87 return this.add(this);
88 }
89
90 @Override
91 public Fp6 mul(Fp6 o) {
92
93 Fp2 a1 = a, b1 = b, c1 = c;
94 Fp2 a2 = o.a, b2 = o.b, c2 = o.c;
95
96 Fp2 a1a2 = a1.mul(a2);
97 Fp2 b1b2 = b1.mul(b2);
98 Fp2 c1c2 = c1.mul(c2);
99
100 Fp2 ra = a1a2.add(b1.add(c1).mul(b2.add(c2)).sub(b1b2).sub(c1c2).mulByNonResidue());
101 Fp2 rb = a1.add(b1).mul(a2.add(b2)).sub(a1a2).sub(b1b2).add(c1c2.mulByNonResidue());
102 Fp2 rc = a1.add(c1).mul(a2.add(c2)).sub(a1a2).add(b1b2).sub(c1c2);
103
104 return new Fp6(ra, rb, rc);
105 }
106
107 Fp6 mul(Fp2 o) {
108
109 Fp2 ra = a.mul(o);
110 Fp2 rb = b.mul(o);
111 Fp2 rc = c.mul(o);
112
113 return new Fp6(ra, rb, rc);
114 }
115
116 Fp6 mulByNonResidue() {
117
118 Fp2 ra = NON_RESIDUE.mul(c);
119 Fp2 rb = a;
120 Fp2 rc = b;
121
122 return new Fp6(ra, rb, rc);
123 }
124
125 @Override
126 public Fp6 add(Fp6 o) {
127
128 Fp2 ra = a.add(o.a);
129 Fp2 rb = b.add(o.b);
130 Fp2 rc = c.add(o.c);
131
132 return new Fp6(ra, rb, rc);
133 }
134
135 @Override
136 public Fp6 sub(Fp6 o) {
137
138 Fp2 ra = a.sub(o.a);
139 Fp2 rb = b.sub(o.b);
140 Fp2 rc = c.sub(o.c);
141
142 return new Fp6(ra, rb, rc);
143 }
144
145 @Override
146 public Fp6 inverse() {
147
148 /* From "High-Speed Software Implementation of the Optimal Ate Pairing over Barreto-Naehrig Curves"; Algorithm 17 */
149
150 Fp2 t0 = a.squared();
151 Fp2 t1 = b.squared();
152 Fp2 t2 = c.squared();
153 Fp2 t3 = a.mul(b);
154 Fp2 t4 = a.mul(c);
155 Fp2 t5 = b.mul(c);
156 Fp2 c0 = t0.sub(t5.mulByNonResidue());
157 Fp2 c1 = t2.mulByNonResidue().sub(t3);
158 Fp2 c2 = t1.sub(t4); // typo in paper referenced above. should be "-" as per Scott, but is "*"
159 Fp2 t6 = a.mul(c0).add((c.mul(c1).add(b.mul(c2))).mulByNonResidue()).inverse();
160
161 Fp2 ra = t6.mul(c0);
162 Fp2 rb = t6.mul(c1);
163 Fp2 rc = t6.mul(c2);
164
165 return new Fp6(ra, rb, rc);
166 }
167
168 @Override
169 public Fp6 negate() {
170 return new Fp6(a.negate(), b.negate(), c.negate());
171 }
172
173 @Override
174 public boolean isZero() {
175 return this.equals(ZERO);
176 }
177
178 @Override
179 public boolean isValid() {
180 return a.isValid() && b.isValid() && c.isValid();
181 }
182
183 Fp6 frobeniusMap(int power) {
184
185 Fp2 ra = a.frobeniusMap(power);
186 Fp2 rb = FROBENIUS_COEFFS_B[power % 6].mul(b.frobeniusMap(power));
187 Fp2 rc = FROBENIUS_COEFFS_C[power % 6].mul(c.frobeniusMap(power));
188
189 return new Fp6(ra, rb, rc);
190 }
191
192 @Override
193 public boolean equals(Object o) {
194 if (this == o) {return true;}
195 if (!(o instanceof Fp6)) {return false;}
196
197 Fp6 fp6 = (Fp6) o;
198
199 if (a != null ? !a.equals(fp6.a) : fp6.a != null) {return false;}
200 if (b != null ? !b.equals(fp6.b) : fp6.b != null) {return false;}
201 return !(c != null ? !c.equals(fp6.c) : fp6.c != null);
202 }
203
204 @Override
205 public int hashCode() {
206 return Objects.hash(a,b,c);
207 }
208
209 private static final Fp2[] FROBENIUS_COEFFS_B = {
210
211 new Fp2(BigInteger.ONE,
212 BigInteger.ZERO),
213
214 new Fp2(new BigInteger("21575463638280843010398324269430826099269044274347216827212613867836435027261"),
215 new BigInteger("10307601595873709700152284273816112264069230130616436755625194854815875713954")),
216
217 new Fp2(new BigInteger("21888242871839275220042445260109153167277707414472061641714758635765020556616"),
218 BigInteger.ZERO),
219
220 new Fp2(new BigInteger("3772000881919853776433695186713858239009073593817195771773381919316419345261"),
221 new BigInteger("2236595495967245188281701248203181795121068902605861227855261137820944008926")),
222
223 new Fp2(new BigInteger("2203960485148121921418603742825762020974279258880205651966"),
224 BigInteger.ZERO),
225
226 new Fp2(new BigInteger("18429021223477853657660792034369865839114504446431234726392080002137598044644"),
227 new BigInteger("9344045779998320333812420223237981029506012124075525679208581902008406485703"))
228 };
229
230 private static final Fp2[] FROBENIUS_COEFFS_C = {
231
232 new Fp2(BigInteger.ONE,
233 BigInteger.ZERO),
234
235 new Fp2(new BigInteger("2581911344467009335267311115468803099551665605076196740867805258568234346338"),
236 new BigInteger("19937756971775647987995932169929341994314640652964949448313374472400716661030")),
237
238 new Fp2(new BigInteger("2203960485148121921418603742825762020974279258880205651966"),
239 BigInteger.ZERO),
240
241 new Fp2(new BigInteger("5324479202449903542726783395506214481928257762400643279780343368557297135718"),
242 new BigInteger("16208900380737693084919495127334387981393726419856888799917914180988844123039")),
243
244 new Fp2(new BigInteger("21888242871839275220042445260109153167277707414472061641714758635765020556616"),
245 BigInteger.ZERO),
246
247 new Fp2(new BigInteger("13981852324922362344252311234282257507216387789820983642040889267519694726527"),
248 new BigInteger("7629828391165209371577384193250820201684255241773809077146787135900891633097"))
249 };
250 }