This commit is contained in:
2026-08-20 10:59:55 +09:00
parent 90bbda0872
commit 731fac1875
@@ -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);
}
}
}