Coverage Summary for Class: Fp12 (co.rsk.crypto.altbn128java)

Class Class, % Method, % Line, %
Fp12 0% (0/1) 0% (0/22) 0% (0/145)


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_12 <br/> 27  * <br/> 28  * 29  * "p" equals 21888242871839275222246405745257275088696311157297823662689037894645226208583, <br/> 30  * elements of Fp_12 are represented with 2 elements of {@link Fp6} <br/> 31  * <br/> 32  * 33  * Field arithmetic is ported from <a href="https://github.com/scipr-lab/libff/blob/master/libff/algebra/fields/fp12_2over3over2.tcc">libff</a> 34  * 35  * @author Mikhail Kalinin 36  * @since 02.09.2017 37  */ 38 class Fp12 implements Field<Fp12> { 39  40  public static final Fp12 ZERO = new Fp12(Fp6.ZERO, Fp6.ZERO); 41  public static final Fp12 _1 = new Fp12(Fp6._1, Fp6.ZERO); 42  43  private Fp6 a; 44  45  public Fp6 a() { 46  return a; 47  } 48  49  public Fp6 b() { 50  return b; 51  } 52  53  private Fp6 b; 54  55  Fp12 (Fp6 a, Fp6 b) { 56  this.a = a; 57  this.b = b; 58  } 59  60  @Override 61  public Fp12 squared() { 62  63  Fp6 ab = a.mul(b); 64  65  Fp6 ra = a.add(b).mul(a.add(b.mulByNonResidue())).sub(ab).sub(ab.mulByNonResidue()); 66  Fp6 rb = ab.add(ab); 67  68  return new Fp12(ra, rb); 69  } 70  71  @Override 72  public Fp12 dbl() { 73  return null; 74  } 75  76  Fp12 mulBy024(Fp2 ell0, Fp2 ellVW, Fp2 ellVV) { 77  78  Fp2 z0 = a.a(); 79  Fp2 z1 = a.b(); 80  Fp2 z2 = a.c(); 81  Fp2 z3 = b.a(); 82  Fp2 z4 = b.b(); 83  Fp2 z5 = b.c(); 84  85  Fp2 x0 = ell0; 86  Fp2 x2 = ellVV; 87  Fp2 x4 = ellVW; 88  89  Fp2 t0, t1, t2, s0, t3, t4, d0, d2, d4, s1; 90  91  d0 = z0.mul(x0); 92  d2 = z2.mul(x2); 93  d4 = z4.mul(x4); 94  t2 = z0.add(z4); 95  t1 = z0.add(z2); 96  s0 = z1.add(z3).add(z5); 97  98  // For z.a_.a_ = z0. 99  s1 = z1.mul(x2); 100  t3 = s1.add(d4); 101  t4 = Fp6.NON_RESIDUE.mul(t3).add(d0); 102  z0 = t4; 103  104  // For z.a_.b_ = z1 105  t3 = z5.mul(x4); 106  s1 = s1.add(t3); 107  t3 = t3.add(d2); 108  t4 = Fp6.NON_RESIDUE.mul(t3); 109  t3 = z1.mul(x0); 110  s1 = s1.add(t3); 111  t4 = t4.add(t3); 112  z1 = t4; 113  114  // For z.a_.c_ = z2 115  t0 = x0.add(x2); 116  t3 = t1.mul(t0).sub(d0).sub(d2); 117  t4 = z3.mul(x4); 118  s1 = s1.add(t4); 119  t3 = t3.add(t4); 120  121  // For z.b_.a_ = z3 (z3 needs z2) 122  t0 = z2.add(z4); 123  z2 = t3; 124  t1 = x2.add(x4); 125  t3 = t0.mul(t1).sub(d2).sub(d4); 126  t4 = Fp6.NON_RESIDUE.mul(t3); 127  t3 = z3.mul(x0); 128  s1 = s1.add(t3); 129  t4 = t4.add(t3); 130  z3 = t4; 131  132  // For z.b_.b_ = z4 133  t3 = z5.mul(x2); 134  s1 = s1.add(t3); 135  t4 = Fp6.NON_RESIDUE.mul(t3); 136  t0 = x0.add(x4); 137  t3 = t2.mul(t0).sub(d0).sub(d4); 138  t4 = t4.add(t3); 139  z4 = t4; 140  141  // For z.b_.c_ = z5. 142  t0 = x0.add(x2).add(x4); 143  t3 = s0.mul(t0).sub(s1); 144  z5 = t3; 145  146  return new Fp12(new Fp6(z0, z1, z2), new Fp6(z3, z4, z5)); 147  } 148  149  @Override 150  public Fp12 add(Fp12 o) { 151  return new Fp12(a.add(o.a), b.add(o.b)); 152  } 153  154  @Override 155  public Fp12 mul(Fp12 o) { 156  157  Fp6 a2 = o.a, b2 = o.b; 158  Fp6 a1 = a, b1 = b; 159  160  Fp6 a1a2 = a1.mul(a2); 161  Fp6 b1b2 = b1.mul(b2); 162  163  Fp6 ra = a1a2.add(b1b2.mulByNonResidue()); 164  Fp6 rb = a1.add(b1).mul(a2.add(b2)).sub(a1a2).sub(b1b2); 165  166  return new Fp12(ra, rb); 167  } 168  169  @Override 170  public Fp12 sub(Fp12 o) { 171  return new Fp12(a.sub(o.a), b.sub(o.b)); 172  } 173  174  @Override 175  public Fp12 inverse() { 176  177  Fp6 t0 = a.squared(); 178  Fp6 t1 = b.squared(); 179  Fp6 t2 = t0.sub(t1.mulByNonResidue()); 180  Fp6 t3 = t2.inverse(); 181  182  Fp6 ra = a.mul(t3); 183  Fp6 rb = b.mul(t3).negate(); 184  185  return new Fp12(ra, rb); 186  } 187  188  @Override 189  public Fp12 negate() { 190  return new Fp12(a.negate(), b.negate()); 191  } 192  193  @Override 194  public boolean isZero() { 195  return this.equals(ZERO); 196  } 197  198  @Override 199  public boolean isValid() { 200  return a.isValid() && b.isValid(); 201  } 202  203  Fp12 frobeniusMap(int power) { 204  205  Fp6 ra = a.frobeniusMap(power); 206  Fp6 rb = b.frobeniusMap(power).mul(FROBENIUS_COEFFS_B[power % 12]); 207  208  return new Fp12(ra, rb); 209  } 210  211  Fp12 cyclotomicSquared() { 212  213  Fp2 z0 = a.a(); 214  Fp2 z4 = a.b(); 215  Fp2 z3 = a.c(); 216  Fp2 z2 = b.a(); 217  Fp2 z1 = b.b(); 218  Fp2 z5 = b.c(); 219  220  Fp2 t0, t1, t2, t3, t4, t5, tmp; 221  222  // t0 + t1*y = (z0 + z1*y)^2 = a^2 223  tmp = z0.mul(z1); 224  t0 = z0.add(z1).mul(z0.add(Fp6.NON_RESIDUE.mul(z1))).sub(tmp).sub(Fp6.NON_RESIDUE.mul(tmp)); 225  t1 = tmp.add(tmp); 226  // t2 + t3*y = (z2 + z3*y)^2 = b^2 227  tmp = z2.mul(z3); 228  t2 = z2.add(z3).mul(z2.add(Fp6.NON_RESIDUE.mul(z3))).sub(tmp).sub(Fp6.NON_RESIDUE.mul(tmp)); 229  t3 = tmp.add(tmp); 230  // t4 + t5*y = (z4 + z5*y)^2 = c^2 231  tmp = z4.mul(z5); 232  t4 = z4.add(z5).mul(z4.add(Fp6.NON_RESIDUE.mul(z5))).sub(tmp).sub(Fp6.NON_RESIDUE.mul(tmp)); 233  t5 = tmp.add(tmp); 234  235  // for A 236  237  // z0 = 3 * t0 - 2 * z0 238  z0 = t0.sub(z0); 239  z0 = z0.add(z0); 240  z0 = z0.add(t0); 241  // z1 = 3 * t1 + 2 * z1 242  z1 = t1.add(z1); 243  z1 = z1.add(z1); 244  z1 = z1.add(t1); 245  246  // for B 247  248  // z2 = 3 * (xi * t5) + 2 * z2 249  tmp = Fp6.NON_RESIDUE.mul(t5); 250  z2 = tmp.add(z2); 251  z2 = z2.add(z2); 252  z2 = z2.add(tmp); 253  254  // z3 = 3 * t4 - 2 * z3 255  z3 = t4.sub(z3); 256  z3 = z3.add(z3); 257  z3 = z3.add(t4); 258  259  // for C 260  261  // z4 = 3 * t2 - 2 * z4 262  z4 = t2.sub(z4); 263  z4 = z4.add(z4); 264  z4 = z4.add(t2); 265  266  // z5 = 3 * t3 + 2 * z5 267  z5 = t3.add(z5); 268  z5 = z5.add(z5); 269  z5 = z5.add(t3); 270  271  return new Fp12(new Fp6(z0, z4, z3), new Fp6(z2, z1, z5)); 272  } 273  274  Fp12 cyclotomicExp(BigInteger pow) { 275  276  Fp12 res = _1; 277  278  for (int i = pow.bitLength() - 1; i >=0; i--) { 279  res = res.cyclotomicSquared(); 280  281  if (pow.testBit(i)) { 282  res = res.mul(this); 283  } 284  } 285  286  return res; 287  } 288  289  Fp12 unitaryInverse() { 290  291  Fp6 ra = a; 292  Fp6 rb = b.negate(); 293  294  return new Fp12(ra, rb); 295  } 296  297  Fp12 negExp(BigInteger exp) { 298  return this.cyclotomicExp(exp).unitaryInverse(); 299  } 300  301  @Override 302  public boolean equals(Object o) { 303  if (this == o) {return true;} 304  if (!(o instanceof Fp12)) {return false;} 305  306  Fp12 fp12 = (Fp12) o; 307  308  if (a != null ? !a.equals(fp12.a) : fp12.a != null) {return false;} 309  return !(b != null ? !b.equals(fp12.b) : fp12.b != null); 310  311  } 312  313  @Override 314  public int hashCode() { 315  return Objects.hash(a,b); 316  } 317  318  @Override 319  public String toString() { 320  return String.format( 321  "Fp12 (%s; %s)\n" + 322  " (%s; %s)\n" + 323  " (%s; %s)\n" + 324  " (%s; %s)\n" + 325  " (%s; %s)\n" + 326  " (%s; %s)\n", 327  328  a.a().a(), a.a().b(), 329  a.b().a(), a.b().b(), 330  a.c().a(), a.c().b(), 331  b.a().a(), b.a().b(), 332  b.b().a(), b.b().b(), 333  b.c().a(), b.c().b() 334  ); 335  } 336  337  private static final Fp2[] FROBENIUS_COEFFS_B = new Fp2[] { 338  339  new Fp2(BigInteger.ONE, 340  BigInteger.ZERO), 341  342  new Fp2(new BigInteger("8376118865763821496583973867626364092589906065868298776909617916018768340080"), 343  new BigInteger("16469823323077808223889137241176536799009286646108169935659301613961712198316")), 344  345  new Fp2(new BigInteger("21888242871839275220042445260109153167277707414472061641714758635765020556617"), 346  BigInteger.ZERO), 347  348  new Fp2(new BigInteger("11697423496358154304825782922584725312912383441159505038794027105778954184319"), 349  new BigInteger("303847389135065887422783454877609941456349188919719272345083954437860409601")), 350  351  new Fp2(new BigInteger("21888242871839275220042445260109153167277707414472061641714758635765020556616"), 352  BigInteger.ZERO), 353  354  new Fp2(new BigInteger("3321304630594332808241809054958361220322477375291206261884409189760185844239"), 355  new BigInteger("5722266937896532885780051958958348231143373700109372999374820235121374419868")), 356  357  new Fp2(new BigInteger("21888242871839275222246405745257275088696311157297823662689037894645226208582"), 358  BigInteger.ZERO), 359  360  new Fp2(new BigInteger("13512124006075453725662431877630910996106405091429524885779419978626457868503"), 361  new BigInteger("5418419548761466998357268504080738289687024511189653727029736280683514010267")), 362  363  new Fp2(new BigInteger("2203960485148121921418603742825762020974279258880205651966"), 364  BigInteger.ZERO), 365  366  new Fp2(new BigInteger("10190819375481120917420622822672549775783927716138318623895010788866272024264"), 367  new BigInteger("21584395482704209334823622290379665147239961968378104390343953940207365798982")), 368  369  new Fp2(new BigInteger("2203960485148121921418603742825762020974279258880205651967"), 370  BigInteger.ZERO), 371  372  new Fp2(new BigInteger("18566938241244942414004596690298913868373833782006617400804628704885040364344"), 373  new BigInteger("16165975933942742336466353786298926857552937457188450663314217659523851788715")) 374  }; 375 }