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 }