WIP
This commit is contained in:
@@ -3,13 +3,13 @@
|
||||
* Project: Gajumaru Core Java Libraries <gajumaru.io>
|
||||
*
|
||||
* This program is dual-licensed:
|
||||
* 1) Under the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option)
|
||||
* 1) Under the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version (AGPL-3.0-or-later).
|
||||
*
|
||||
* 2) Under a commercial/proprietary license available directly from QPQ AG.
|
||||
* If you wish to use this software outside the strict constraints of the
|
||||
* AGPLv3 (e.g. within a closed-source or proprietary product), you must
|
||||
* If you wish to use this software outside the strict constraints of the
|
||||
* AGPLv3 (e.g. within a closed-source or proprietary product), you must
|
||||
* purchase a commercial license from QPQ AG.
|
||||
*
|
||||
* Authors:
|
||||
@@ -23,7 +23,7 @@ package swiss.qpq.gajumaru.core.crypto;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import swiss.qpq.gajumaru.core.tools.CryptoUtils;
|
||||
|
||||
/**
|
||||
@@ -32,50 +32,77 @@ import swiss.qpq.gajumaru.core.tools.CryptoUtils;
|
||||
*/
|
||||
public final class Ed25519 {
|
||||
|
||||
private static final long TWO_TO_25 = 1L << 25;
|
||||
private static final long TWO_TO_26 = 1L << 26;
|
||||
private static final BigInteger P_FIELD = BigInteger.valueOf(2).pow(255).subtract(BigInteger.valueOf(19));
|
||||
|
||||
// Precomputed limbs for Ed25519 constants (Radix 2^25.5) from RFC 8032
|
||||
private static final long[] BX = {52811034L, 25909283L, 16144682L, 17082669L, 27570973L, 30858332L, 40966398L, 8378388L, 20764389L, 8758491L};
|
||||
private static final long[] BY = {40265304L, 26843545L, 13421772L, 20132659L, 26843545L, 6710886L, 53687091L, 13421772L, 40265318L, 26843545L};
|
||||
private static final long[] BX = {52811034L, 25909283L, 16144682L, 17082669L, 27570973L, 30858332L, 40966398L, 8378388L, 20764389L, 8758491L};
|
||||
private static final long[] BY = {40265304L, 26843545L, 13421772L, 20132659L, 26843545L, 6710886L, 53687091L, 13421772L, 40265318L, 26843545L};
|
||||
private static final long[] BXY = {28827043L, 27438313L, 39759291L, 244362L, 8635006L, 11264893L, 19351346L, 13413597L, 16611511L, 27139452L};
|
||||
private static final long[] D = {56195235L, 13857412L, 51736253L, 6949390L, 114729L, 24766616L, 60832955L, 30306712L, 48412415L, 21499315L};
|
||||
private static final long[] D2 = {45281625L, 27714825L, 36363642L, 13898781L, 229458L, 15978800L, 54557047L, 27058993L, 29715967L, 9444199L};
|
||||
private static final long[] I = {17187054L, 16663501L, 25252512L, 26698L, 9007192L, 25056900L, 31130252L, 16580L, 54723919L, 2713947L};
|
||||
private static final long[] D = {56195235L, 13857412L, 51736253L, 6949390L, 114729L, 24766616L, 60832955L, 30306712L, 48412415L, 21499315L};
|
||||
private static final long[] D2 = {45281625L, 27714825L, 36363642L, 13898781L, 229458L, 15978800L, 54557047L, 27058993L, 29715967L, 9444199L};
|
||||
private static final long[] I = {17187054L, 16663501L, 25252512L, 26698L, 9007192L, 25056900L, 31130252L, 16580L, 54723919L, 2713947L};
|
||||
|
||||
// Precomputed limbs for 2 * P_FIELD to eliminate negative limb carries during subtraction
|
||||
private static final long[] TWO_P = {
|
||||
0x3FFFFDAL, 0x1FFFFFFL, 0x3FFFFFFL, 0x1FFFFFFL, 0x3FFFFFFL,
|
||||
0x1FFFFFFL, 0x3FFFFFFL, 0x1FFFFFFL, 0x3FFFFFFL, 0x1FFFFFFL
|
||||
};
|
||||
|
||||
private static final class Ge {
|
||||
final long[] X = new long[10], Y = new long[10], Z = new long[10], T = new long[10];
|
||||
void wipe() { CryptoUtils.wipe(X); CryptoUtils.wipe(Y); CryptoUtils.wipe(Z); CryptoUtils.wipe(T); }
|
||||
}
|
||||
|
||||
private static final class Scratch {
|
||||
final long[] a = new long[10], b = new long[10], c = new long[10], d = new long[10], e = new long[10], f = new long[10], g = new long[10], h = new long[10], tmp = new long[10], t19 = new long[19];
|
||||
final Ge geTmp = new Ge();
|
||||
void wipe() {
|
||||
CryptoUtils.wipe(a); CryptoUtils.wipe(b); CryptoUtils.wipe(c); CryptoUtils.wipe(d);
|
||||
CryptoUtils.wipe(e); CryptoUtils.wipe(f); CryptoUtils.wipe(g); CryptoUtils.wipe(h);
|
||||
CryptoUtils.wipe(tmp); CryptoUtils.wipe(t19); geTmp.wipe();
|
||||
CryptoUtils.wipe(X);
|
||||
CryptoUtils.wipe(Y);
|
||||
CryptoUtils.wipe(Z);
|
||||
CryptoUtils.wipe(T);
|
||||
}
|
||||
}
|
||||
|
||||
private Ed25519() {}
|
||||
private static final class Scratch {
|
||||
final long[] a = new long[10], b = new long[10], c = new long[10], d = new long[10],
|
||||
e = new long[10], f = new long[10], g = new long[10], h = new long[10],
|
||||
tmp = new long[10], t19 = new long[19];
|
||||
final Ge geTmp = new Ge();
|
||||
|
||||
void wipe() {
|
||||
CryptoUtils.wipe(a);
|
||||
CryptoUtils.wipe(b);
|
||||
CryptoUtils.wipe(c);
|
||||
CryptoUtils.wipe(d);
|
||||
CryptoUtils.wipe(e);
|
||||
CryptoUtils.wipe(f);
|
||||
CryptoUtils.wipe(g);
|
||||
CryptoUtils.wipe(h);
|
||||
CryptoUtils.wipe(tmp);
|
||||
CryptoUtils.wipe(t19);
|
||||
geTmp.wipe();
|
||||
}
|
||||
}
|
||||
|
||||
private Ed25519() {
|
||||
}
|
||||
|
||||
public static byte[] publicKey(byte[] seed) {
|
||||
byte[] hash = sha512(seed);
|
||||
byte[] s = Arrays.copyOfRange(hash, 0, 32);
|
||||
s[0] &= 248; s[31] &= 127; s[31] |= 64;
|
||||
s[0] &= 248;
|
||||
s[31] &= 127;
|
||||
s[31] |= 64;
|
||||
Scratch sc = new Scratch();
|
||||
Ge A_point = scalarMulBase(s, sc);
|
||||
byte[] A = compress(A_point, sc);
|
||||
A_point.wipe(); sc.wipe(); CryptoUtils.wipe(hash); CryptoUtils.wipe(s);
|
||||
A_point.wipe();
|
||||
sc.wipe();
|
||||
CryptoUtils.wipe(hash);
|
||||
CryptoUtils.wipe(s);
|
||||
return A;
|
||||
}
|
||||
|
||||
public static byte[] sign(byte[] seed, byte[] message) {
|
||||
byte[] hash = sha512(seed);
|
||||
byte[] s = Arrays.copyOfRange(hash, 0, 32);
|
||||
s[0] &= 248; s[31] &= 127; s[31] |= 64;
|
||||
s[0] &= 248;
|
||||
s[31] &= 127;
|
||||
s[31] |= 64;
|
||||
byte[] prefix = Arrays.copyOfRange(hash, 32, 64);
|
||||
byte[] rHash = sha512(prefix, message);
|
||||
reduce(rHash);
|
||||
@@ -92,9 +119,16 @@ public final class Ed25519 {
|
||||
byte[] sig = new byte[64];
|
||||
System.arraycopy(R, 0, sig, 0, 32);
|
||||
System.arraycopy(S, 0, sig, 32, 32);
|
||||
R_point.wipe(); sc.wipe(); CryptoUtils.wipe(hash); CryptoUtils.wipe(s);
|
||||
CryptoUtils.wipe(prefix); CryptoUtils.wipe(rHash); CryptoUtils.wipe(r);
|
||||
CryptoUtils.wipe(kHash); CryptoUtils.wipe(k); CryptoUtils.wipe(A);
|
||||
R_point.wipe();
|
||||
sc.wipe();
|
||||
CryptoUtils.wipe(hash);
|
||||
CryptoUtils.wipe(s);
|
||||
CryptoUtils.wipe(prefix);
|
||||
CryptoUtils.wipe(rHash);
|
||||
CryptoUtils.wipe(r);
|
||||
CryptoUtils.wipe(kHash);
|
||||
CryptoUtils.wipe(k);
|
||||
CryptoUtils.wipe(A);
|
||||
return sig;
|
||||
}
|
||||
|
||||
@@ -113,15 +147,25 @@ public final class Ed25519 {
|
||||
ge_double_scalarmul_vartime(R_expected, S_bytes, A, k, sc);
|
||||
byte[] R_check = compress(R_expected, sc);
|
||||
boolean ok = Arrays.equals(R_bytes, R_check);
|
||||
A.wipe(); R_expected.wipe(); sc.wipe(); CryptoUtils.wipe(kHash); CryptoUtils.wipe(k);
|
||||
A.wipe();
|
||||
R_expected.wipe();
|
||||
sc.wipe();
|
||||
CryptoUtils.wipe(kHash);
|
||||
CryptoUtils.wipe(k);
|
||||
return ok;
|
||||
}
|
||||
|
||||
private static Ge scalarMulBase(byte[] scalar, Scratch s) {
|
||||
Ge p = new Ge();
|
||||
fe_copy(p.X, BX); fe_copy(p.Y, BY); fe_1(p.Z); fe_copy(p.T, BXY);
|
||||
fe_copy(p.X, BX);
|
||||
fe_copy(p.Y, BY);
|
||||
fe_1(p.Z);
|
||||
fe_copy(p.T, BXY);
|
||||
Ge res = new Ge();
|
||||
fe_0(res.X); fe_1(res.Y); fe_1(res.Z); fe_0(res.T);
|
||||
fe_0(res.X);
|
||||
fe_1(res.Y);
|
||||
fe_1(res.Z);
|
||||
fe_0(res.T);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int bit = ((scalar[i / 8] & 0xFF) >>> (i % 8)) & 1;
|
||||
ge_add(s.geTmp, res, p, s);
|
||||
@@ -138,20 +182,29 @@ public final class Ed25519 {
|
||||
fe_neg(kA.X, kA.X);
|
||||
fe_neg(kA.T, kA.T);
|
||||
ge_add(r, sB, kA, sc);
|
||||
sB.wipe(); kA.wipe();
|
||||
sB.wipe();
|
||||
kA.wipe();
|
||||
}
|
||||
|
||||
private static Ge scalarMul(Ge p, byte[] scalar, Scratch s) {
|
||||
Ge res = new Ge();
|
||||
fe_0(res.X); fe_1(res.Y); fe_1(res.Z); fe_0(res.T);
|
||||
fe_0(res.X);
|
||||
fe_1(res.Y);
|
||||
fe_1(res.Z);
|
||||
fe_0(res.T);
|
||||
Ge q = new Ge();
|
||||
fe_copy(q.X, p.X); fe_copy(q.Y, p.Y); fe_copy(q.Z, p.Z); fe_copy(q.T, p.T);
|
||||
fe_copy(q.X, p.X);
|
||||
fe_copy(q.Y, p.Y);
|
||||
fe_copy(q.Z, p.Z);
|
||||
fe_copy(q.T, p.T);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int bit = ((scalar[i / 8] & 0xFF) >>> (i % 8)) & 1;
|
||||
if (bit == 1) {
|
||||
ge_add(s.geTmp, res, q, s);
|
||||
fe_copy(res.X, s.geTmp.X); fe_copy(res.Y, s.geTmp.Y);
|
||||
fe_copy(res.Z, s.geTmp.Z); fe_copy(res.T, s.geTmp.T);
|
||||
fe_copy(res.X, s.geTmp.X);
|
||||
fe_copy(res.Y, s.geTmp.Y);
|
||||
fe_copy(res.Z, s.geTmp.Z);
|
||||
fe_copy(res.T, s.geTmp.T);
|
||||
}
|
||||
ge_double(q, q, s);
|
||||
}
|
||||
@@ -160,29 +213,52 @@ public final class Ed25519 {
|
||||
}
|
||||
|
||||
private static void ge_add(Ge r, Ge p1, Ge p2, Scratch s) {
|
||||
fe_sub(s.a, p1.Y, p1.X); fe_sub(s.b, p2.Y, p2.X); fe_mul(s.a, s.a, s.b, s.t19);
|
||||
fe_add(s.b, p1.Y, p1.X); fe_add(s.c, p2.Y, p2.X); fe_mul(s.b, s.b, s.c, s.t19);
|
||||
fe_mul(s.tmp, p1.T, p2.T, s.t19); fe_mul(s.c, s.tmp, D2, s.t19);
|
||||
fe_mul(s.d, p1.Z, p2.Z, s.t19); fe_add(s.d, s.d, s.d);
|
||||
fe_sub(s.e, s.b, s.a); fe_sub(s.f, s.d, s.c); fe_add(s.g, s.d, s.c); fe_add(s.h, s.b, s.a);
|
||||
fe_mul(r.X, s.e, s.f, s.t19); fe_mul(r.Y, s.g, s.h, s.t19);
|
||||
fe_mul(r.Z, s.f, s.g, s.t19); fe_mul(r.T, s.e, s.h, s.t19);
|
||||
fe_sub(s.a, p1.Y, p1.X);
|
||||
fe_sub(s.b, p2.Y, p2.X);
|
||||
fe_mul(s.a, s.a, s.b, s.t19);
|
||||
fe_add(s.b, p1.Y, p1.X);
|
||||
fe_add(s.c, p2.Y, p2.X);
|
||||
fe_mul(s.b, s.b, s.c, s.t19);
|
||||
fe_mul(s.tmp, p1.T, p2.T, s.t19);
|
||||
fe_mul(s.c, s.tmp, D2, s.t19);
|
||||
fe_mul(s.d, p1.Z, p2.Z, s.t19);
|
||||
fe_add(s.d, s.d, s.d);
|
||||
fe_sub(s.e, s.b, s.a);
|
||||
fe_sub(s.f, s.d, s.c);
|
||||
fe_add(s.g, s.d, s.c);
|
||||
fe_add(s.h, s.b, s.a);
|
||||
fe_mul(r.X, s.e, s.f, s.t19);
|
||||
fe_mul(r.Y, s.g, s.h, s.t19);
|
||||
fe_mul(r.Z, s.f, s.g, s.t19);
|
||||
fe_mul(r.T, s.e, s.h, s.t19);
|
||||
}
|
||||
|
||||
private static void ge_double(Ge r, Ge p, Scratch s) {
|
||||
fe_sq(s.a, p.X, s.t19); fe_sq(s.b, p.Y, s.t19); fe_sq(s.c, p.Z, s.t19); fe_add(s.c, s.c, s.c);
|
||||
fe_neg(s.d, s.a); fe_add(s.tmp, p.X, p.Y); fe_sq(s.e, s.tmp, s.t19);
|
||||
fe_add(s.tmp, s.a, s.b); fe_sub(s.e, s.e, s.tmp);
|
||||
fe_add(s.g, s.d, s.b); fe_sub(s.f, s.g, s.c); fe_sub(s.h, s.d, s.b);
|
||||
fe_mul(r.X, s.e, s.f, s.t19); fe_mul(r.Y, s.g, s.h, s.t19);
|
||||
fe_mul(r.Z, s.f, s.g, s.t19); fe_mul(r.T, s.e, s.h, s.t19);
|
||||
fe_sq(s.a, p.X, s.t19);
|
||||
fe_sq(s.b, p.Y, s.t19);
|
||||
fe_sq(s.c, p.Z, s.t19);
|
||||
fe_add(s.c, s.c, s.c);
|
||||
fe_neg(s.d, s.a);
|
||||
fe_add(s.tmp, p.X, p.Y);
|
||||
fe_sq(s.e, s.tmp, s.t19);
|
||||
fe_add(s.tmp, s.a, s.b);
|
||||
fe_sub(s.e, s.e, s.tmp);
|
||||
fe_add(s.g, s.d, s.b);
|
||||
fe_sub(s.f, s.g, s.c);
|
||||
fe_sub(s.h, s.d, s.b);
|
||||
fe_mul(r.X, s.e, s.f, s.t19);
|
||||
fe_mul(r.Y, s.g, s.h, s.t19);
|
||||
fe_mul(r.Z, s.f, s.g, s.t19);
|
||||
fe_mul(r.T, s.e, s.h, s.t19);
|
||||
}
|
||||
|
||||
private static void ge_cmov(Ge r, Ge p, int b) {
|
||||
long m = -(long) b;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
r.X[i] ^= (m & (r.X[i] ^ p.X[i])); r.Y[i] ^= (m & (r.Y[i] ^ p.Y[i]));
|
||||
r.Z[i] ^= (m & (r.Z[i] ^ p.Z[i])); r.T[i] ^= (m & (r.T[i] ^ p.T[i]));
|
||||
r.X[i] ^= (m & (r.X[i] ^ p.X[i]));
|
||||
r.Y[i] ^= (m & (r.Y[i] ^ p.Y[i]));
|
||||
r.Z[i] ^= (m & (r.Z[i] ^ p.Z[i]));
|
||||
r.T[i] ^= (m & (r.T[i] ^ p.T[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +267,7 @@ public final class Ed25519 {
|
||||
Ge p = new Ge();
|
||||
fe_frombytes(p.Y, b);
|
||||
fe_1(p.Z);
|
||||
fe_sq(s.a, p.Y, s.t19);
|
||||
fe_sq(s.a, p.Y, s.t19);
|
||||
fe_mul(s.b, s.a, D, s.t19);
|
||||
fe_sub(s.a, s.a, p.Z);
|
||||
fe_add(s.b, s.b, p.Z);
|
||||
@@ -216,37 +292,121 @@ public final class Ed25519 {
|
||||
}
|
||||
|
||||
private static byte[] compress(Ge p, Scratch s) {
|
||||
fe_invert(s.a, p.Z, s); fe_mul(s.b, p.X, s.a, s.t19); fe_mul(s.c, p.Y, s.a, s.t19);
|
||||
fe_invert(s.a, p.Z, s);
|
||||
fe_mul(s.b, p.X, s.a, s.t19);
|
||||
fe_mul(s.c, p.Y, s.a, s.t19);
|
||||
byte[] out = fe_contract(s.c);
|
||||
if (fe_isnegative(s.b) == 1) out[31] |= (byte) 0x80;
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void fe_0(long[] h) { Arrays.fill(h, 0); }
|
||||
private static void fe_1(long[] h) { Arrays.fill(h, 0); h[0] = 1; }
|
||||
private static void fe_copy(long[] h, long[] f) { System.arraycopy(f, 0, h, 0, 10); }
|
||||
private static void fe_add(long[] h, long[] f, long[] g) { for (int i = 0; i < 10; i++) h[i] = f[i] + g[i]; }
|
||||
private static void fe_sub(long[] h, long[] f, long[] g) { for (int i = 0; i < 10; i++) h[i] = f[i] - g[i]; }
|
||||
private static void fe_neg(long[] h, long[] f) { for (int i = 0; i < 10; i++) h[i] = -f[i]; }
|
||||
|
||||
private static void fe_mul(long[] out, long[] in1, long[] in2, long[] t) {
|
||||
BigInteger ba = new BigInteger(1, reverse(fe_contract(in1)));
|
||||
BigInteger bb = new BigInteger(1, reverse(fe_contract(in2)));
|
||||
BigInteger br = ba.multiply(bb).mod(P_FIELD);
|
||||
byte[] r = br.toByteArray();
|
||||
byte[] b = new byte[32];
|
||||
for (int i = 0; i < Math.min(r.length, 32); i++) b[i] = r[r.length - 1 - i];
|
||||
fe_frombytes(out, b);
|
||||
private static void fe_0(long[] h) {
|
||||
Arrays.fill(h, 0);
|
||||
}
|
||||
|
||||
private static void fe_sq(long[] out, long[] in, long[] t) {
|
||||
fe_mul(out, in, in, t);
|
||||
private static void fe_1(long[] h) {
|
||||
Arrays.fill(h, 0);
|
||||
h[0] = 1;
|
||||
}
|
||||
|
||||
private static byte[] reverse(byte[] b) {
|
||||
byte[] r = new byte[b.length];
|
||||
for (int i = 0; i < b.length; i++) r[i] = b[b.length - 1 - i];
|
||||
return r;
|
||||
private static void fe_copy(long[] h, long[] f) {
|
||||
System.arraycopy(f, 0, h, 0, 10);
|
||||
}
|
||||
|
||||
private static void fe_add(long[] h, long[] f, long[] g) {
|
||||
for (int i = 0; i < 10; i++) h[i] = f[i] + g[i];
|
||||
}
|
||||
|
||||
private static void fe_sub(long[] h, long[] f, long[] g) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
h[i] = (f[i] + TWO_P[i]) - g[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static void fe_neg(long[] h, long[] f) {
|
||||
for (int i = 0; i < 10; i++) h[i] = -f[i];
|
||||
}
|
||||
|
||||
private static void fe_mul(long[] out, long[] f, long[] g, long[] t) {
|
||||
long f0 = f[0], f1 = f[1], f2 = f[2], f3 = f[3], f4 = f[4],
|
||||
f5 = f[5], f6 = f[6], f7 = f[7], f8 = f[8], f9 = f[9];
|
||||
long g0 = g[0], g1 = g[1], g2 = g[2], g3 = g[3], g4 = g[4],
|
||||
g5 = g[5], g6 = g[6], g7 = g[7], g8 = g[8], g9 = g[9];
|
||||
|
||||
long g1_19 = g1 * 19, g2_19 = g2 * 19, g3_19 = g3 * 19, g4_19 = g4 * 19,
|
||||
g5_19 = g5 * 19, g6_19 = g6 * 19, g7_19 = g7 * 19, g8_19 = g8 * 19, g9_19 = g9 * 19;
|
||||
|
||||
long r0 = f0 * g0 + f1 * g9_19 + f2 * g8_19 + f3 * g7_19 + f4 * g6_19 + f5 * g5_19 + f6 * g4_19 + f7 * g3_19 + f8 * g2_19 + f9 * g1_19;
|
||||
long r1 = f0 * g1 + f1 * g0 + f2 * g9_19 + f3 * g8_19 + f4 * g7_19 + f5 * g6_19 + f6 * g5_19 + f7 * g4_19 + f8 * g3_19 + f9 * g2_19;
|
||||
long r2 = f0 * g2 + f1 * g1 + f2 * g0 + f3 * g9_19 + f4 * g8_19 + f5 * g7_19 + f6 * g6_19 + f7 * g5_19 + f8 * g4_19 + f9 * g3_19;
|
||||
long r3 = f0 * g3 + f1 * g2 + f2 * g1 + f3 * g0 + f4 * g9_19 + f5 * g8_19 + f6 * g7_19 + f7 * g6_19 + f8 * g5_19 + f9 * g4_19;
|
||||
long r4 = f0 * g4 + f1 * g3 + f2 * g2 + f3 * g1 + f4 * g0 + f5 * g9_19 + f6 * g8_19 + f7 * g7_19 + f8 * g6_19 + f9 * g5_19;
|
||||
long r5 = f0 * g5 + f1 * g4 + f2 * g3 + f3 * g2 + f4 * g1 + f5 * g0 + f6 * g9_19 + f7 * g8_19 + f8 * g7_19 + f9 * g6_19;
|
||||
long r6 = f0 * g6 + f1 * g5 + f2 * g4 + f3 * g3 + f4 * g2 + f5 * g1 + f6 * g0 + f7 * g9_19 + f8 * g8_19 + f9 * g7_19;
|
||||
long r7 = f0 * g7 + f1 * g6 + f2 * g5 + f3 * g4 + f4 * g3 + f5 * g2 + f6 * g1 + f7 * g0 + f8 * g9_19 + f9 * g8_19;
|
||||
long r8 = f0 * g8 + f1 * g7 + f2 * g6 + f3 * g5 + f4 * g4 + f5 * g3 + f6 * g2 + f7 * g1 + f8 * g0 + f9 * g9_19;
|
||||
long r9 = f0 * g9 + f1 * g8 + f2 * g7 + f3 * g6 + f4 * g5 + f5 * g4 + f6 * g3 + f7 * g2 + f8 * g1 + f9 * g0;
|
||||
|
||||
r1 *= 2; r3 *= 2; r5 *= 2; r7 *= 2; r9 *= 2;
|
||||
|
||||
long c;
|
||||
c = r0 >> 26; r1 += c; r0 &= 0x3FFFFFFL;
|
||||
c = r1 >> 25; r2 += c; r1 &= 0x1FFFFFFL;
|
||||
c = r2 >> 26; r3 += c; r2 &= 0x3FFFFFFL;
|
||||
c = r3 >> 25; r4 += c; r3 &= 0x1FFFFFFL;
|
||||
c = r4 >> 26; r5 += c; r4 &= 0x3FFFFFFL;
|
||||
c = r5 >> 25; r6 += c; r5 &= 0x1FFFFFFL;
|
||||
c = r6 >> 26; r7 += c; r6 &= 0x3FFFFFFL;
|
||||
c = r7 >> 25; r8 += c; r7 &= 0x1FFFFFFL;
|
||||
c = r8 >> 26; r9 += c; r8 &= 0x3FFFFFFL;
|
||||
c = r9 >> 25; r0 += c * 19; r9 &= 0x1FFFFFFL;
|
||||
|
||||
c = r0 >> 26; r1 += c; r0 &= 0x3FFFFFFL;
|
||||
|
||||
out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4;
|
||||
out[5] = r5; out[6] = r6; out[7] = r7; out[8] = r8; out[9] = r9;
|
||||
}
|
||||
|
||||
|
||||
private static void fe_sq(long[] out, long[] f, long[] t) {
|
||||
long f0 = f[0], f1 = f[1], f2 = f[2], f3 = f[3], f4 = f[4],
|
||||
f5 = f[5], f6 = f[6], f7 = f[7], f8 = f[8], f9 = f[9];
|
||||
|
||||
long f1_2 = f1 * 2, f2_2 = f2 * 2, f3_2 = f3 * 2, f4_2 = f4 * 2,
|
||||
f5_2 = f5 * 2, f6_2 = f6 * 2, f7_2 = f7 * 2, f8_2 = f8 * 2, f9_2 = f9 * 2;
|
||||
|
||||
long f1_19 = f1 * 19, f2_19 = f2 * 19, f3_19 = f3 * 19, f4_19 = f4 * 19,
|
||||
f5_19 = f5 * 19, f6_19 = f6 * 19, f7_19 = f7 * 19, f8_19 = f8 * 19, f9_19 = f9 * 19;
|
||||
|
||||
long r0 = f0 * f0 + f1_2 * f9_19 + f2_2 * f8_19 + f3_2 * f7_19 + f4_2 * f6_19 + f5 * f5_19;
|
||||
long r1 = f0 * f1_2 + f2 * f9_19 + f3 * f8_19 + f4 * f7_19 + f5 * f6_19;
|
||||
long r2 = f0 * f2_2 + f1 * f1 + f3_2 * f9_19 + f4_2 * f8_19 + f5_2 * f7_19 + f6 * f6_19;
|
||||
long r3 = f0 * f3_2 + f1_2 * f2 + f4 * f9_19 + f5 * f8_19 + f6 * f7_19;
|
||||
long r4 = f0 * f4_2 + f1_2 * f3_2 + f2 * f2 + f5_2 * f9_19 + f6_2 * f8_19 + f7 * f7_19;
|
||||
long r5 = f0 * f5_2 + f1_2 * f4 + f2_2 * f3 + f6 * f9_19 + f7 * f8_19;
|
||||
long r6 = f0 * f6_2 + f1_2 * f5_2 + f2_2 * f4_2 + f3 * f3 + f7_2 * f9_19 + f8 * f8_19;
|
||||
long r7 = f0 * f7_2 + f1_2 * f6 + f2_2 * f5 + f3_2 * f4 + f8 * f9_19;
|
||||
long r8 = f0 * f8_2 + f1_2 * f7_2 + f2_2 * f6_2 + f3_2 * f5_2 + f4 * f4 + f9 * f9_19;
|
||||
long r9 = f0 * f9_2 + f1_2 * f8 + f2_2 * f7 + f3_2 * f6 + f4_2 * f5;
|
||||
|
||||
r1 *= 2; r3 *= 2; r5 *= 2; r7 *= 2; r9 *= 2;
|
||||
|
||||
long c;
|
||||
c = r0 >> 26; r1 += c; r0 &= 0x3FFFFFFL;
|
||||
c = r1 >> 25; r2 += c; r1 &= 0x1FFFFFFL;
|
||||
c = r2 >> 26; r3 += c; r2 &= 0x3FFFFFFL;
|
||||
c = r3 >> 25; r4 += c; r3 &= 0x1FFFFFFL;
|
||||
c = r4 >> 26; r5 += c; r4 &= 0x3FFFFFFL;
|
||||
c = r5 >> 25; r6 += c; r5 &= 0x1FFFFFFL;
|
||||
c = r6 >> 26; r7 += c; r6 &= 0x3FFFFFFL;
|
||||
c = r7 >> 25; r8 += c; r7 &= 0x1FFFFFFL;
|
||||
c = r8 >> 26; r9 += c; r8 &= 0x3FFFFFFL;
|
||||
c = r9 >> 25; r0 += c * 19; r9 &= 0x1FFFFFFL;
|
||||
|
||||
c = r0 >> 26; r1 += c; r0 &= 0x3FFFFFFL;
|
||||
|
||||
out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4;
|
||||
out[5] = r5; out[6] = r6; out[7] = r7; out[8] = r8; out[9] = r9;
|
||||
}
|
||||
|
||||
private static void fe_frombytes(long[] h, byte[] s) {
|
||||
@@ -269,7 +429,7 @@ public final class Ed25519 {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
long carry = h[i] >> (i % 2 == 0 ? 26 : 25);
|
||||
h[i] &= (i % 2 == 0 ? 0x3FFFFFFL : 0x1FFFFFFL);
|
||||
h[i+1] += carry;
|
||||
h[i + 1] += carry;
|
||||
}
|
||||
long carry = h[9] >> 25;
|
||||
h[9] &= 0x1FFFFFFL;
|
||||
@@ -280,7 +440,7 @@ public final class Ed25519 {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
long carry = hplus19[i] >> (i % 2 == 0 ? 26 : 25);
|
||||
hplus19[i] &= (i % 2 == 0 ? 0x3FFFFFFL : 0x1FFFFFFL);
|
||||
hplus19[i+1] += carry;
|
||||
hplus19[i + 1] += carry;
|
||||
}
|
||||
long carry = hplus19[9] >> 25;
|
||||
hplus19[9] &= 0x1FFFFFFL;
|
||||
@@ -305,7 +465,7 @@ public final class Ed25519 {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
long carry = h[i] >> (i % 2 == 0 ? 26 : 25);
|
||||
h[i] &= (i % 2 == 0 ? 0x3FFFFFFL : 0x1FFFFFFL);
|
||||
h[i+1] += carry;
|
||||
h[i + 1] += carry;
|
||||
}
|
||||
long carry = h[9] >> 25;
|
||||
h[9] &= 0x1FFFFFFL;
|
||||
@@ -314,30 +474,120 @@ public final class Ed25519 {
|
||||
|
||||
private static void fe_invert(long[] out, long[] z, Scratch s) {
|
||||
long[] z2 = new long[10], z9 = new long[10], z11 = new long[10], t0 = new long[10], t1 = new long[10], t2 = new long[10];
|
||||
fe_sq(z2, z, s.t19); fe_sq(t1, z2, s.t19); fe_sq(t0, t1, s.t19); fe_mul(z9, t0, z, s.t19); fe_mul(z11, z9, z2, s.t19);
|
||||
fe_sq(t0, z11, s.t19); fe_mul(t2, t0, z9, s.t19);
|
||||
fe_sq(t0, t2, s.t19); for (int i = 1; i < 5; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(t1, t0, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19); for (int i = 1; i < 10; i++) { fe_sq(t2, t0, s.t19); fe_copy(t0, t2); } fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19); for (int i = 1; i < 20; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19); for (int i = 1; i < 10; i++) { fe_sq(t0, t1, s.t19); fe_copy(t1, t0); } fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19); for (int i = 1; i < 50; i++) { fe_sq(t2, t0, s.t19); fe_copy(t0, t2); } fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19); for (int i = 1; i < 100; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19); for (int i = 1; i < 50; i++) { fe_sq(t0, t1, s.t19); fe_copy(t1, t0); } fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19); for (int i = 1; i < 5; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(out, t0, z11, s.t19);
|
||||
fe_sq(z2, z, s.t19);
|
||||
fe_sq(t1, z2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
fe_mul(z9, t0, z, s.t19);
|
||||
fe_mul(z11, z9, z2, s.t19);
|
||||
fe_sq(t0, z11, s.t19);
|
||||
fe_mul(t2, t0, z9, s.t19);
|
||||
fe_sq(t0, t2, s.t19);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(t1, t0, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
fe_sq(t2, t0, s.t19);
|
||||
fe_copy(t0, t2);
|
||||
}
|
||||
fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19);
|
||||
for (int i = 1; i < 20; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
fe_sq(t0, t1, s.t19);
|
||||
fe_copy(t1, t0);
|
||||
}
|
||||
fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
for (int i = 1; i < 50; i++) {
|
||||
fe_sq(t2, t0, s.t19);
|
||||
fe_copy(t0, t2);
|
||||
}
|
||||
fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19);
|
||||
for (int i = 1; i < 100; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 50; i++) {
|
||||
fe_sq(t0, t1, s.t19);
|
||||
fe_copy(t1, t0);
|
||||
}
|
||||
fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(out, t0, z, s.t19);
|
||||
}
|
||||
|
||||
private static void fe_pow22523(long[] out, long[] z, Scratch s) {
|
||||
long[] t0 = new long[10], t1 = new long[10], t2 = new long[10];
|
||||
fe_sq(t0, z, s.t19); fe_sq(t1, t0, s.t19); fe_sq(t1, t1, s.t19); fe_mul(t1, t1, z, s.t19); fe_mul(t0, t0, t1, s.t19);
|
||||
fe_sq(t0, t0, s.t19); fe_mul(t0, t0, t1, s.t19); fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 5; i++) { fe_sq(t2, t1, s.t19); fe_copy(t1, t2); } fe_mul(t1, t1, t0, s.t19);
|
||||
fe_sq(t2, t1, s.t19); for (int i = 1; i < 10; i++) { fe_sq(t0, t2, s.t19); fe_copy(t2, t0); } fe_mul(t2, t2, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19); for (int i = 1; i < 20; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19); for (int i = 1; i < 10; i++) { fe_sq(t0, t1, s.t19); fe_copy(t1, t0); } fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19); for (int i = 1; i < 50; i++) { fe_sq(t2, t0, s.t19); fe_copy(t0, t2); } fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19); for (int i = 1; i < 100; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19); for (int i = 1; i < 50; i++) { fe_sq(t0, t1, s.t19); fe_copy(t1, t0); } fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19); for (int i = 1; i < 2; i++) { fe_sq(t1, t0, s.t19); fe_copy(t0, t1); } fe_mul(out, t0, z, s.t19);
|
||||
fe_sq(t0, z, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_sq(t1, t1, s.t19);
|
||||
fe_mul(t1, t1, z, s.t19);
|
||||
fe_mul(t0, t0, t1, s.t19);
|
||||
fe_sq(t0, t0, s.t19);
|
||||
fe_mul(t0, t0, t1, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 5; i++) {
|
||||
fe_sq(t2, t1, s.t19);
|
||||
fe_copy(t1, t2);
|
||||
}
|
||||
fe_mul(t1, t1, t0, s.t19);
|
||||
fe_sq(t2, t1, s.t19);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
fe_sq(t0, t2, s.t19);
|
||||
fe_copy(t2, t0);
|
||||
}
|
||||
fe_mul(t2, t2, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19);
|
||||
for (int i = 1; i < 20; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
fe_sq(t0, t1, s.t19);
|
||||
fe_copy(t1, t0);
|
||||
}
|
||||
fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
for (int i = 1; i < 50; i++) {
|
||||
fe_sq(t2, t0, s.t19);
|
||||
fe_copy(t0, t2);
|
||||
}
|
||||
fe_mul(t2, t0, t1, s.t19);
|
||||
fe_sq(t0, t2, s.t19);
|
||||
for (int i = 1; i < 100; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(t0, t0, t2, s.t19);
|
||||
fe_sq(t1, t0, s.t19);
|
||||
for (int i = 1; i < 50; i++) {
|
||||
fe_sq(t0, t1, s.t19);
|
||||
fe_copy(t1, t0);
|
||||
}
|
||||
fe_mul(t1, t1, t2, s.t19);
|
||||
fe_sq(t0, t1, s.t19);
|
||||
for (int i = 1; i < 2; i++) {
|
||||
fe_sq(t1, t0, s.t19);
|
||||
fe_copy(t0, t1);
|
||||
}
|
||||
fe_mul(out, t0, z, s.t19);
|
||||
}
|
||||
|
||||
private static boolean fe_isnonzero(long[] h) {
|
||||
@@ -377,70 +627,213 @@ public final class Ed25519 {
|
||||
long s21 = 2097151 & (load3(s, 55) >> 1);
|
||||
long s22 = 2097151 & (load4(s, 57) >> 6);
|
||||
long s23 = (load4(s, 60) >> 3);
|
||||
|
||||
s11 += s23 * 666643; s12 += s23 * 470296; s13 += s23 * 654183; s14 -= s23 * 997805; s15 += s23 * 136657; s16 -= s23 * 683901;
|
||||
s10 += s22 * 666643; s11 += s22 * 470296; s12 += s22 * 654183; s13 -= s22 * 997805; s14 += s22 * 136657; s15 -= s22 * 683901;
|
||||
s9 += s21 * 666643; s10 += s21 * 470296; s11 += s21 * 654183; s12 -= s21 * 997805; s13 += s21 * 136657; s14 -= s21 * 683901;
|
||||
s8 += s20 * 666643; s9 += s20 * 470296; s10 += s20 * 654183; s11 -= s20 * 997805; s12 += s20 * 136657; s13 -= s20 * 683901;
|
||||
s7 += s19 * 666643; s8 += s19 * 470296; s9 += s19 * 654183; s10 -= s19 * 997805; s11 += s19 * 136657; s12 -= s19 * 683901;
|
||||
s6 += s18 * 666643; s7 += s18 * 470296; s8 += s18 * 654183; s9 -= s18 * 997805; s10 += s18 * 136657; s11 -= s18 * 683901;
|
||||
|
||||
long c6 = (s6 + (1 << 20)) >> 21; s7 += c6; s6 -= c6 << 21;
|
||||
long c8 = (s8 + (1 << 20)) >> 21; s9 += c8; s8 -= c8 << 21;
|
||||
long c10 = (s10 + (1 << 20)) >> 21; s11 += c10; s10 -= c10 << 21;
|
||||
long c12 = (s12 + (1 << 20)) >> 21; s13 += c12; s12 -= c12 << 21;
|
||||
long c14 = (s14 + (1 << 20)) >> 21; s15 += c14; s14 -= c14 << 21;
|
||||
long c16 = (s16 + (1 << 20)) >> 21; s17 += c16; s16 -= c16 << 21;
|
||||
long c7 = (s7 + (1 << 20)) >> 21; s8 += c7; s7 -= c7 << 21;
|
||||
long c9 = (s9 + (1 << 20)) >> 21; s10 += c9; s9 -= c9 << 21;
|
||||
long c11 = (s11 + (1 << 20)) >> 21; s12 += c11; s11 -= c11 << 21;
|
||||
long c13 = (s13 + (1 << 20)) >> 21; s14 += c13; s13 -= c13 << 21;
|
||||
long c15 = (s15 + (1 << 20)) >> 21; s16 += c15; s15 -= c15 << 21;
|
||||
|
||||
s5 += s17 * 666643; s6 += s17 * 470296; s7 += s17 * 654183; s8 -= s17 * 997805; s9 += s17 * 136657; s10 -= s17 * 683901;
|
||||
s4 += s16 * 666643; s5 += s16 * 470296; s6 += s16 * 654183; s7 -= s16 * 997805; s8 += s16 * 136657; s9 -= s16 * 683901;
|
||||
s3 += s15 * 666643; s4 += s15 * 470296; s5 += s15 * 654183; s6 -= s15 * 997805; s7 += s15 * 136657; s8 -= s15 * 683901;
|
||||
s2 += s14 * 666643; s3 += s14 * 470296; s4 += s14 * 654183; s5 -= s14 * 997805; s6 += s14 * 136657; s7 -= s14 * 683901;
|
||||
s1 += s13 * 666643; s2 += s13 * 470296; s3 += s13 * 654183; s4 -= s13 * 997805; s5 += s13 * 136657; s6 -= s13 * 683901;
|
||||
s0 += s12 * 666643; s1 += s12 * 470296; s2 += s12 * 654183; s3 -= s12 * 997805; s4 += s12 * 136657; s5 -= s12 * 683901;
|
||||
|
||||
long cc0 = (s0 + (1 << 20)) >> 21; s1 += cc0; s0 -= cc0 << 21;
|
||||
long cc2 = (s2 + (1 << 20)) >> 21; s3 += cc2; s2 -= cc2 << 21;
|
||||
long cc4 = (s4 + (1 << 20)) >> 21; s5 += cc4; s4 -= cc4 << 21;
|
||||
long cc6 = (s6 + (1 << 20)) >> 21; s7 += cc6; s6 -= cc6 << 21;
|
||||
long cc8 = (s8 + (1 << 20)) >> 21; s9 += cc8; s8 -= cc8 << 21;
|
||||
long cc10 = (s10 + (1 << 20)) >> 21; s11 += cc10; s10 -= cc10 << 21;
|
||||
long cc1 = (s1 + (1 << 20)) >> 21; s2 += cc1; s1 -= cc1 << 21;
|
||||
long cc3 = (s3 + (1 << 20)) >> 21; s4 += cc3; s3 -= cc3 << 21;
|
||||
long cc5 = (s5 + (1 << 20)) >> 21; s6 += cc5; s5 -= cc5 << 21;
|
||||
long cc7 = (s7 + (1 << 20)) >> 21; s8 += cc7; s7 -= cc7 << 21;
|
||||
long cc9 = (s9 + (1 << 20)) >> 21; s10 += cc9; s9 -= cc9 << 21;
|
||||
long cc11 = (s11 + (1 << 20)) >> 21; long s12_2 = cc11; s11 -= cc11 << 21;
|
||||
|
||||
s0 += s12_2 * 666643; s1 += s12_2 * 470296; s2 += s12_2 * 654183; s3 -= s12_2 * 997805; s4 += s12_2 * 136657; s5 -= s12_2 * 683901;
|
||||
|
||||
long ccc0 = s0 >> 21; s1 += ccc0; s0 -= ccc0 << 21;
|
||||
long ccc1 = s1 >> 21; s2 += ccc1; s1 -= ccc1 << 21;
|
||||
long ccc2 = s2 >> 21; s3 += ccc2; s2 -= ccc2 << 21;
|
||||
long ccc3 = s3 >> 21; s4 += ccc3; s3 -= ccc3 << 21;
|
||||
long ccc4 = s4 >> 21; s5 += ccc4; s4 -= ccc4 << 21;
|
||||
long ccc5 = s5 >> 21; s6 += ccc5; s5 -= ccc5 << 21;
|
||||
long ccc6 = s6 >> 21; s7 += ccc6; s6 -= ccc6 << 21;
|
||||
long ccc7 = s7 >> 21; s8 += ccc7; s7 -= ccc7 << 21;
|
||||
long ccc8 = s8 >> 21; s9 += ccc8; s8 -= ccc8 << 21;
|
||||
long ccc9 = s9 >> 21; s10 += ccc9; s9 -= ccc9 << 21;
|
||||
long ccc10 = s10 >> 21; s11 += ccc10; s10 -= ccc10 << 21;
|
||||
long ccc11 = s11 >> 21; long s12_3 = ccc11; s11 -= ccc11 << 21;
|
||||
|
||||
s0 += s12_3 * 666643; s1 += s12_3 * 470296; s2 += s12_3 * 654183; s3 -= s12_3 * 997805; s4 += s12_3 * 136657; s5 -= s12_3 * 683901;
|
||||
|
||||
long sccc0 = s0 >> 21; s1 += sccc0; s0 -= sccc0 << 21;
|
||||
long sccc1 = s1 >> 21; s2 += sccc1; s1 -= sccc1 << 21;
|
||||
long sccc2 = s2 >> 21; s3 += sccc2; s2 -= sccc2 << 21;
|
||||
long sccc3 = s3 >> 21; s4 += sccc3; s3 -= sccc3 << 21;
|
||||
long sccc4 = s4 >> 21; s5 += sccc4; s4 -= sccc4 << 21;
|
||||
long sccc5 = s5 >> 21; s6 += sccc5; s5 -= sccc5 << 21;
|
||||
|
||||
s11 += s23 * 666643;
|
||||
s12 += s23 * 470296;
|
||||
s13 += s23 * 654183;
|
||||
s14 -= s23 * 997805;
|
||||
s15 += s23 * 136657;
|
||||
s16 -= s23 * 683901;
|
||||
s10 += s22 * 666643;
|
||||
s11 += s22 * 470296;
|
||||
s12 += s22 * 654183;
|
||||
s13 -= s22 * 997805;
|
||||
s14 += s22 * 136657;
|
||||
s15 -= s22 * 683901;
|
||||
s9 += s21 * 666643;
|
||||
s10 += s21 * 470296;
|
||||
s11 += s21 * 654183;
|
||||
s12 -= s21 * 997805;
|
||||
s13 += s21 * 136657;
|
||||
s14 -= s21 * 683901;
|
||||
s8 += s20 * 666643;
|
||||
s9 += s20 * 470296;
|
||||
s10 += s20 * 654183;
|
||||
s11 -= s20 * 997805;
|
||||
s12 += s20 * 136657;
|
||||
s13 -= s20 * 683901;
|
||||
s7 += s19 * 666643;
|
||||
s8 += s19 * 470296;
|
||||
s9 += s19 * 654183;
|
||||
s10 -= s19 * 997805;
|
||||
s11 += s19 * 136657;
|
||||
s12 -= s19 * 683901;
|
||||
s6 += s18 * 666643;
|
||||
s7 += s18 * 470296;
|
||||
s8 += s18 * 654183;
|
||||
s9 -= s18 * 997805;
|
||||
s10 += s18 * 136657;
|
||||
s11 -= s18 * 683901;
|
||||
long c6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += c6;
|
||||
s6 -= c6 << 21;
|
||||
long c8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += c8;
|
||||
s8 -= c8 << 21;
|
||||
long c10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += c10;
|
||||
s10 -= c10 << 21;
|
||||
long c12 = (s12 + (1 << 20)) >> 21;
|
||||
s13 += c12;
|
||||
s12 -= c12 << 21;
|
||||
long c14 = (s14 + (1 << 20)) >> 21;
|
||||
s15 += c14;
|
||||
s14 -= c14 << 21;
|
||||
long c16 = (s16 + (1 << 20)) >> 21;
|
||||
s17 += c16;
|
||||
s16 -= c16 << 21;
|
||||
long c7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += c7;
|
||||
s7 -= c7 << 21;
|
||||
long c9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += c9;
|
||||
s9 -= c9 << 21;
|
||||
long c11 = (s11 + (1 << 20)) >> 21;
|
||||
s12 += c11;
|
||||
s11 -= c11 << 21;
|
||||
long c13 = (s13 + (1 << 20)) >> 21;
|
||||
s14 += c13;
|
||||
s13 -= c13 << 21;
|
||||
long c15 = (s15 + (1 << 20)) >> 21;
|
||||
s16 += c15;
|
||||
s15 -= c15 << 21;
|
||||
s5 += s17 * 666643;
|
||||
s6 += s17 * 470296;
|
||||
s7 += s17 * 654183;
|
||||
s8 -= s17 * 997805;
|
||||
s9 += s17 * 136657;
|
||||
s10 -= s17 * 683901;
|
||||
s4 += s16 * 666643;
|
||||
s5 += s16 * 470296;
|
||||
s6 += s16 * 654183;
|
||||
s7 -= s16 * 997805;
|
||||
s8 += s16 * 136657;
|
||||
s9 -= s16 * 683901;
|
||||
s3 += s15 * 666643;
|
||||
s4 += s15 * 470296;
|
||||
s5 += s15 * 654183;
|
||||
s6 -= s15 * 997805;
|
||||
s7 += s15 * 136657;
|
||||
s8 -= s15 * 683901;
|
||||
s2 += s14 * 666643;
|
||||
s3 += s14 * 470296;
|
||||
s4 += s14 * 654183;
|
||||
s5 -= s14 * 997805;
|
||||
s6 += s14 * 136657;
|
||||
s7 -= s14 * 683901;
|
||||
s1 += s13 * 666643;
|
||||
s2 += s13 * 470296;
|
||||
s3 += s13 * 654183;
|
||||
s4 -= s13 * 997805;
|
||||
s5 += s13 * 136657;
|
||||
s6 -= s13 * 683901;
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
s3 -= s12 * 997805;
|
||||
s4 += s12 * 136657;
|
||||
s5 -= s12 * 683901;
|
||||
long cc0 = (s0 + (1 << 20)) >> 21;
|
||||
s1 += cc0;
|
||||
s0 -= cc0 << 21;
|
||||
long cc2 = (s2 + (1 << 20)) >> 21;
|
||||
s3 += cc2;
|
||||
s2 -= cc2 << 21;
|
||||
long cc4 = (s4 + (1 << 20)) >> 21;
|
||||
s5 += cc4;
|
||||
s4 -= cc4 << 21;
|
||||
long cc6 = (s6 + (1 << 20)) >> 21;
|
||||
s7 += cc6;
|
||||
s6 -= cc6 << 21;
|
||||
long cc8 = (s8 + (1 << 20)) >> 21;
|
||||
s9 += cc8;
|
||||
s8 -= cc8 << 21;
|
||||
long cc10 = (s10 + (1 << 20)) >> 21;
|
||||
s11 += cc10;
|
||||
s10 -= cc10 << 21;
|
||||
long cc1 = (s1 + (1 << 20)) >> 21;
|
||||
s2 += cc1;
|
||||
s1 -= cc1 << 21;
|
||||
long cc3 = (s3 + (1 << 20)) >> 21;
|
||||
s4 += cc3;
|
||||
s3 -= cc3 << 21;
|
||||
long cc5 = (s5 + (1 << 20)) >> 21;
|
||||
s6 += cc5;
|
||||
s5 -= cc5 << 21;
|
||||
long cc7 = (s7 + (1 << 20)) >> 21;
|
||||
s8 += cc7;
|
||||
s7 -= cc7 << 21;
|
||||
long cc9 = (s9 + (1 << 20)) >> 21;
|
||||
s10 += cc9;
|
||||
s9 -= cc9 << 21;
|
||||
long cc11 = (s11 + (1 << 20)) >> 21;
|
||||
long s12_2 = cc11;
|
||||
s11 -= cc11 << 21;
|
||||
s0 += s12_2 * 666643;
|
||||
s1 += s12_2 * 470296;
|
||||
s2 += s12_2 * 654183;
|
||||
s3 -= s12_2 * 997805;
|
||||
s4 += s12_2 * 136657;
|
||||
s5 -= s12_2 * 683901;
|
||||
long ccc0 = s0 >> 21;
|
||||
s1 += ccc0;
|
||||
s0 -= ccc0 << 21;
|
||||
long ccc1 = s1 >> 21;
|
||||
s2 += ccc1;
|
||||
s1 -= ccc1 << 21;
|
||||
long ccc2 = s2 >> 21;
|
||||
s3 += ccc2;
|
||||
s2 -= ccc2 << 21;
|
||||
long ccc3 = s3 >> 21;
|
||||
s4 += ccc3;
|
||||
s3 -= ccc3 << 21;
|
||||
long ccc4 = s4 >> 21;
|
||||
s5 += ccc4;
|
||||
s4 -= ccc4 << 21;
|
||||
long ccc5 = s5 >> 21;
|
||||
s6 += ccc5;
|
||||
s5 -= ccc5 << 21;
|
||||
long ccc6 = s6 >> 21;
|
||||
s7 += ccc6;
|
||||
s6 -= ccc6 << 21;
|
||||
long ccc7 = s7 >> 21;
|
||||
s8 += ccc7;
|
||||
s7 -= ccc7 << 21;
|
||||
long ccc8 = s8 >> 21;
|
||||
s9 += ccc8;
|
||||
s8 -= ccc8 << 21;
|
||||
long ccc9 = s9 >> 21;
|
||||
s10 += ccc9;
|
||||
s9 -= ccc9 << 21;
|
||||
long ccc10 = s10 >> 21;
|
||||
s11 += ccc10;
|
||||
s10 -= ccc10 << 21;
|
||||
long ccc11 = s11 >> 21;
|
||||
long s12_3 = ccc11;
|
||||
s11 -= ccc11 << 21;
|
||||
s0 += s12_3 * 666643;
|
||||
s1 += s12_3 * 470296;
|
||||
s2 += s12_3 * 654183;
|
||||
s3 -= s12_3 * 997805;
|
||||
s4 += s12_3 * 136657;
|
||||
s5 -= s12_3 * 683901;
|
||||
long sccc0 = s0 >> 21;
|
||||
s1 += sccc0;
|
||||
s0 -= sccc0 << 21;
|
||||
long sccc1 = s1 >> 21;
|
||||
s2 += sccc1;
|
||||
s1 -= sccc1 << 21;
|
||||
long sccc2 = s2 >> 21;
|
||||
s3 += sccc2;
|
||||
s2 -= sccc2 << 21;
|
||||
long sccc3 = s3 >> 21;
|
||||
s4 += sccc3;
|
||||
s3 -= sccc3 << 21;
|
||||
long sccc4 = s4 >> 21;
|
||||
s5 += sccc4;
|
||||
s4 -= sccc4 << 21;
|
||||
long sccc5 = s5 >> 21;
|
||||
s6 += sccc5;
|
||||
s5 -= sccc5 << 21;
|
||||
for (int i = 0; i < 32; i++) s[i] = 0;
|
||||
long[] resLimbs = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11};
|
||||
int bitIdx = 0;
|
||||
@@ -486,6 +879,9 @@ public final class Ed25519 {
|
||||
System.arraycopy(buffer, 0, S, 0, 32);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// PUBLIC TEST HOOKS FOR TESTINATOR / EXTERNAL VERIFICATION
|
||||
// =========================================================================
|
||||
public static void testFromBytes(long[] h, byte[] s) {
|
||||
fe_frombytes(h, s);
|
||||
}
|
||||
@@ -506,7 +902,8 @@ public final class Ed25519 {
|
||||
Scratch sc = new Scratch();
|
||||
Ge p = scalarMulBase(in, sc);
|
||||
byte[] out = compress(p, sc);
|
||||
p.wipe(); sc.wipe();
|
||||
p.wipe();
|
||||
sc.wipe();
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -517,7 +914,10 @@ public final class Ed25519 {
|
||||
Ge p3 = new Ge();
|
||||
ge_add(p3, p1, p2, sc);
|
||||
byte[] out = compress(p3, sc);
|
||||
p1.wipe(); p2.wipe(); p3.wipe(); sc.wipe();
|
||||
p1.wipe();
|
||||
p2.wipe();
|
||||
p3.wipe();
|
||||
sc.wipe();
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -530,17 +930,13 @@ public final class Ed25519 {
|
||||
return fe_contract(hr);
|
||||
}
|
||||
|
||||
public static byte[] testFeContract(long[] h) { return fe_contract(h); }
|
||||
public static long[] getBX() { return BX; }
|
||||
public static long[] getBY() { return BY; }
|
||||
public static long[] getD() { return D; }
|
||||
public static long[] getD2() { return D2; }
|
||||
|
||||
private static byte[] sha512(byte[]... parts) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||
for (byte[] p : parts) md.update(p);
|
||||
return md.digest();
|
||||
} catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); }
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user