private static boolean isSquare(int[] x) { int[] t1 = Nat224.create(); int[] t2 = Nat224.create(); Nat224.copy(x, t1); for (int i = 0; i < 7; ++i) { Nat224.copy(t1, t2); SecP224R1Field.squareN(t1, 1 << i, t1); SecP224R1Field.multiply(t1, t2, t1); } SecP224R1Field.squareN(t1, 95, t1); return Nat224.isOne(t1); }
public static int[] fromBigInteger(BigInteger x) { int[] z = Nat224.fromBigInteger(x); if (z[6] == P6 && Nat224.gte(z, P)) { Nat224.subFrom(P, z); } return z; }
public static void reduce(int[] xx, int[] z) { long cc = Nat224.mul33Add(PInv33, xx, 7, xx, 0, z, 0); int c = Nat224.mul33DWordAdd(PInv33, cc, z, 0); // assert c == 0L || c == 1L; if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) { Nat.add33To(7, PInv33, z); } }
int[] tt1 = Nat224.createExt(); int[] t2 = Nat224.create(); int[] t3 = Nat224.create(); int[] t4 = Nat224.create(); int[] H = Nat224.create(); SecP224R1Field.subtract(U1, U2, H); if (Nat224.isZero(H)) if (Nat224.isZero(R)) SecP224R1Field.square(H, HSquared); int[] G = Nat224.create(); SecP224R1Field.multiply(HSquared, H, G); Nat224.mul(S1, G, tt1); c = Nat224.addBothTo(V, V, G); SecP224R1Field.reduce32(c, G);
/** * return a sqrt root - the routine verifies that the calculation returns the right value - if * none exists it returns null. */ public ECFieldElement sqrt() { int[] c = this.x; if (Nat224.isZero(c) || Nat224.isOne(c)) { return this; } int[] nc = Nat224.create(); SecP224R1Field.negate(c, nc); int[] r = Mod.random(SecP224R1Field.P); int[] t = Nat224.create(); if (!isSquare(c)) { return null; } while (!trySqrt(nc, r, t)) { SecP224R1Field.addOne(r, r); } SecP224R1Field.square(t, r); return Nat224.eq(c, r) ? new SecP224R1FieldElement(t) : null; }
public SecP224K1FieldElement() { this.x = Nat224.create(); }
private static boolean trySqrt(int[] nc, int[] r, int[] t) { int[] d1 = Nat224.create(); Nat224.copy(r, d1); int[] e1 = Nat224.create(); e1[0] = 1; int[] f1 = Nat224.create(); RP(nc, d1, e1, f1, t); int[] d0 = Nat224.create(); int[] e0 = Nat224.create(); for (int k = 1; k < 96; ++k) { Nat224.copy(d1, d0); Nat224.copy(e1, e0); RS(d1, e1, f1, t); if (Nat224.isZero(d1)) { Mod.invert(SecP224R1Field.P, e0, t); SecP224R1Field.multiply(t, d0, t); return true; } } return false; } }
int[] Y1Squared = Nat224.create(); SecP224K1Field.square(Y1.x, Y1Squared); int[] T = Nat224.create(); SecP224K1Field.square(Y1Squared, T); int[] M = Nat224.create(); SecP224K1Field.square(X1.x, M); c = Nat224.addBothTo(M, M, M); SecP224K1Field.reduce32(c, M); SecP224K1Field.reduce32(c, S); int[] t1 = Nat224.create(); c = Nat.shiftUpBits(7, T, 3, 0, t1); SecP224K1Field.reduce32(c, t1);
public static void twice(int[] x, int[] z) { int c = Nat.shiftUpBit(7, x, 0, z); if (c != 0 || (z[6] == P6 && Nat224.gte(z, P))) { Nat.add33To(7, PInv33, z); } } }
public static int[] fromBigInteger(BigInteger x) { int[] z = Nat224.fromBigInteger(x); if (z[6] == P6 && Nat224.gte(z, P)) { Nat.add33To(7, PInv33, z); } return z; }
public static void reduce32(int x, int[] z) { if ((x != 0 && Nat224.mul33WordAdd(PInv33, x, z, 0) != 0) || (z[6] == P6 && Nat224.gte(z, P))) { Nat.add33To(7, PInv33, z); } }
private static void RP(int[] nc, int[] d1, int[] e1, int[] f1, int[] t) { Nat224.copy(nc, f1); int[] d0 = Nat224.create(); int[] e0 = Nat224.create(); for (int i = 0; i < 7; ++i) { Nat224.copy(d1, d0); Nat224.copy(e1, e0); int j = 1 << i; while (--j >= 0) { RS(d1, e1, f1, t); } RM(nc, d0, e0, d1, e1, f1, t); } }
public boolean testBitZero() { return Nat224.getBit(x, 0) == 1; }
public static void half(int[] x, int[] z) { if ((x[0] & 1) == 0) { Nat.shiftDownBit(7, x, 0, z); } else { int c = Nat224.add(x, P, z); Nat.shiftDownBit(7, z, c); } }
public boolean isOne() { return Nat224.isOne(x); }
public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof SecP224R1FieldElement)) { return false; } SecP224R1FieldElement o = (SecP224R1FieldElement)other; return Nat224.eq(x, o.x); }