Coverage Summary for Class: Fp2 (co.rsk.crypto.altbn128java)
Class |
Class, %
|
Method, %
|
Line, %
|
Fp2 |
0%
(0/1)
|
0%
(0/21)
|
0%
(0/50)
|
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 F_p2 <br/>
27 * <br/>
28 *
29 * "p" equals 21888242871839275222246405745257275088696311157297823662689037894645226208583,
30 * elements of F_p2 are represented as a polynomials "a * i + b" modulo "i^2 + 1" from the ring F_p[i] <br/>
31 * <br/>
32 *
33 * Field arithmetic is ported from <a href="https://github.com/scipr-lab/libff/blob/master/libff/algebra/fields/fp2.tcc">libff</a> <br/>
34 *
35 * @author Mikhail Kalinin
36 * @since 01.09.2017
37 */
38 class Fp2 implements Field<Fp2> {
39
40 public static final Fp2 ZERO = new Fp2(Fp.ZERO, Fp.ZERO);
41 public static final Fp2 _1 = new Fp2(Fp._1, Fp.ZERO);
42 public static final Fp2 NON_RESIDUE = new Fp2(BigInteger.valueOf(9), BigInteger.ONE);
43
44 private Fp a;
45 private Fp b;
46
47 private static final Fp[] FROBENIUS_COEFFS_B = new Fp[] {
48 new Fp(BigInteger.ONE),
49 new Fp(new BigInteger("21888242871839275222246405745257275088696311157297823662689037894645226208582"))
50 };
51
52
53 public Fp a() {
54 return a;
55 }
56
57 public Fp b() {
58 return b;
59 }
60
61 Fp2(Fp a, Fp b) {
62 this.a = a;
63 this.b = b;
64 }
65
66 Fp2(BigInteger a, BigInteger b) {
67 this(new Fp(a), new Fp(b));
68 }
69
70 @Override
71 public Fp2 squared() {
72
73 // using Complex squaring
74
75 Fp ab = a.mul(b);
76
77 Fp ra = a.add(b).mul(b.mul(Fp.NON_RESIDUE).add(a))
78 .sub(ab).sub(ab.mul(Fp.NON_RESIDUE)); // ra = (a + b)(a + NON_RESIDUE * b) - ab - NON_RESIDUE * b
79 Fp rb = ab.dbl();
80
81 return new Fp2(ra, rb);
82 }
83
84 @Override
85 public Fp2 mul(Fp2 o) {
86
87 Fp aa = a.mul(o.a);
88 Fp bb = b.mul(o.b);
89
90 Fp ra = bb.mul(Fp.NON_RESIDUE).add(aa); // ra = a1 * a2 + NON_RESIDUE * b1 * b2
91 Fp rb = a.add(b).mul(o.a.add(o.b)).sub(aa).sub(bb); // rb = (a1 + b1)(a2 + b2) - a1 * a2 - b1 * b2
92
93 return new Fp2(ra, rb);
94 }
95
96 @Override
97 public Fp2 add(Fp2 o) {
98 return new Fp2(a.add(o.a), b.add(o.b));
99 }
100
101 @Override
102 public Fp2 sub(Fp2 o) {
103 return new Fp2(a.sub(o.a), b.sub(o.b));
104 }
105
106 @Override
107 public Fp2 dbl() {
108 return this.add(this);
109 }
110
111 @Override
112 public Fp2 inverse() {
113
114 Fp t0 = a.squared();
115 Fp t1 = b.squared();
116 Fp t2 = t0.sub(Fp.NON_RESIDUE.mul(t1));
117 Fp t3 = t2.inverse();
118
119 Fp ra = a.mul(t3); // ra = a * t3
120 Fp rb = b.mul(t3).negate(); // rb = -(b * t3)
121
122 return new Fp2(ra, rb);
123 }
124
125 @Override
126 public Fp2 negate() {
127 return new Fp2(a.negate(), b.negate());
128 }
129
130 @Override
131 public boolean isZero() {
132 return this.equals(ZERO);
133 }
134
135 @Override
136 public boolean isValid() {
137 return a.isValid() && b.isValid();
138 }
139
140 static Fp2 create(BigInteger aa, BigInteger bb) {
141
142 Fp a = Fp.create(aa);
143 Fp b = Fp.create(bb);
144
145 return new Fp2(a, b);
146 }
147
148 static Fp2 create(byte[] aa, byte[] bb) {
149
150 Fp a = Fp.create(aa);
151 Fp b = Fp.create(bb);
152
153 return new Fp2(a, b);
154 }
155
156 @Override
157 public boolean equals(Object o) {
158 if (this == o) {return true;}
159 if (o == null || getClass() != o.getClass()) {return false;}
160
161 Fp2 fp2 = (Fp2) o;
162
163 if (a != null ? !a.equals(fp2.a) : fp2.a != null) {return false;}
164 return !(b != null ? !b.equals(fp2.b) : fp2.b != null);
165
166 }
167
168 @Override
169 public int hashCode() {
170 return Objects.hash(a,b);
171 }
172
173 Fp2 frobeniusMap(int power) {
174
175 Fp ra = a;
176 Fp rb = FROBENIUS_COEFFS_B[power % 2].mul(b);
177
178 return new Fp2(ra, rb);
179 }
180
181 Fp2 mulByNonResidue() {
182 return NON_RESIDUE.mul(this);
183 }
184
185 @Override
186 public String toString() {
187 return String.format("%si + %s", a.toString(), b.toString());
188 }
189 }