Skip to content
This repository was archived by the owner on Apr 18, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.whispersystems.curve25519.java.Sha512;
import org.whispersystems.curve25519.java.curve_sigs;
import org.whispersystems.curve25519.java.scalarmult;
import org.whispersystems.curve25519.java.gen_x;

abstract class BaseJavaCurve25519Provider implements Curve25519Provider {

Expand Down Expand Up @@ -74,13 +75,26 @@ public boolean verifySignature(byte[] publicKey, byte[] message, byte[] signatur
}

public byte[] calculateVrfSignature(byte[] random, byte[] privateKey, byte[] message) {
throw new AssertionError("NYI");
byte[] result = new byte[96];
byte[] random32 = new byte[32];
if (random.length >= 32) {
System.arraycopy(random, 0, random32, 0, 32);
} else throw new IllegalArgumentException("too small random");
if (gen_x.generalized_xveddsa_25519_sign(sha512provider, result, privateKey, message, random32)) {
return result;
} else {
throw new IllegalArgumentException();
}
}

public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
throws VrfSignatureVerificationFailedException
{
throw new AssertionError("NYI");
byte[] result = new byte[32];
if (gen_x.generalized_xveddsa_25519_verify(sha512provider, result, signature, publicKey, message) != 0) {
throw new VrfSignatureVerificationFailedException();
}
return result;
}

public byte[] getRandom(int length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ public byte[] calculateVrfSignature(byte[] privateKey, byte[] message) {
* @param message The message that was signed.
* @param signature The unique signature to verify.
*
* @throws VrfSignatureVerificationFailedException when verification is failed
*
* @return The vrf for this signature.
*/
public byte[] verifyVrfSignature(byte[] publicKey, byte[] message, byte[] signature)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.whispersystems.curve25519.java;

public class elligator {
public static int legendre_is_nonsquare(int[] in)
{
int[] temp = new int[10];
byte[] bytes = new byte[32];
fe_pow22523.fe_pow22523(temp, in); /* temp = in^((q-5)/8) */
fe_sq.fe_sq(temp, temp); /* in^((q-5)/4) */
fe_sq.fe_sq(temp, temp); /* in^((q-5)/2) */
fe_mul.fe_mul(temp, temp, in); /* in^((q-3)/2) */
fe_mul.fe_mul(temp, temp, in); /* in^((q-1)/2) */

/* temp is now the Legendre symbol:
* 1 = square
* 0 = input is zero
* -1 = nonsquare
*/
fe_tobytes.fe_tobytes(bytes, temp);
return 1 & bytes[31];
}

public static void elligator(int[] u, int[] r)
{
/* r = input
* gen_x = -A/(1+2r^2) # 2 is nonsquare
* e = (gen_x^3 + Ax^2 + gen_x)^((q-1)/2) # legendre symbol
* if e == 1 (square) or e == 0 (because gen_x == 0 and 2r^2 + 1 == 0)
* u = gen_x
* if e == -1 (nonsquare)
* u = -gen_x - A
*/
int[] A = new int[10], one = new int[10], twor2 = new int[10], twor2plus1 = new int[10], twor2plus1inv = new int[10];
int[] x = new int[10], e = new int[10], Atemp = new int[10], uneg = new int[10];
int nonsquare;

fe_1.fe_1(one);
fe_0.fe_0(A);
A[0] = 486662; /* A = 486662 */

fe_sq2.fe_sq2(twor2, r); /* 2r^2 */
fe_add.fe_add(twor2plus1, twor2, one); /* 1+2r^2 */
fe_invert.fe_invert(twor2plus1inv, twor2plus1); /* 1/(1+2r^2) */
fe_mul.fe_mul(x, twor2plus1inv, A); /* A/(1+2r^2) */
fe_neg.fe_neg(x, x); /* gen_x = -A/(1+2r^2) */

fe_mont_rhs.fe_mont_rhs(e, x); /* e = gen_x^3 + Ax^2 + gen_x */
nonsquare = legendre_is_nonsquare(e);

fe_0.fe_0(Atemp);
fe_cmov.fe_cmov(Atemp, A, nonsquare); /* 0, or A if nonsquare */
fe_add.fe_add(u, x, Atemp); /* gen_x, or gen_x+A if nonsquare */
fe_neg.fe_neg(uneg, u); /* -gen_x, or -gen_x-A if nonsquare */
fe_cmov.fe_cmov(u, uneg, nonsquare); /* gen_x, or -gen_x-A if nonsquare */
}

public static void hash_to_point(Sha512 sha512provider, ge_p3 p, byte[] in)
{
byte[] hash = new byte[64];
int[] h = new int[10], u = new int[10];
ge_p3 p3 = new ge_p3();

sha512provider.calculateDigest(hash, in, in.length);

/* take the high bit as Edwards sign bit */
byte sign_bit = (byte)((hash[31] & 0x80) >> 7);
hash[31] &= 0x7F;
fe_frombytes.fe_frombytes(h, hash);
elligator(u, h);

ge_montx_to_p3.ge_montx_to_p3(p3, u, sign_bit);
ge_scalarmult_cofactor.ge_scalarmult_cofactor(p, p3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.whispersystems.curve25519.java;

public class fe_isequal {
/*
return 1 if f == g
return 0 if f != g
*/
public static int fe_isequal(int[] f, int[] g)
{
int[] h = new int[10];
fe_sub.fe_sub(h, f, g);
return 1 & (((fe_isnonzero.fe_isnonzero(h) & 0xff) - 1) >> 8);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.whispersystems.curve25519.java;

public class fe_isreduced {
public static boolean fe_isreduced(byte[] s)
{
int[] f = new int[10];
byte[] strict = new byte[32];

fe_frombytes.fe_frombytes(f, s);
fe_tobytes.fe_tobytes(strict, f);
return crypto_verify_32.crypto_verify_32(strict, s) == 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.whispersystems.curve25519.java;

public class fe_mont_rhs {
public static void fe_mont_rhs(int[] v2, int[] u) {
int[] A = new int[10], one= new int[10];
int[] u2= new int[10], Au= new int[10], inner= new int[10];

fe_1.fe_1(one);
fe_0.fe_0(A);
A[0] = 486662; /* A = 486662 */

fe_sq.fe_sq(u2, u); /* u^2 */
fe_mul.fe_mul(Au, A, u); /* Au */
fe_add.fe_add(inner, u2, Au); /* u^2 + Au */
fe_add.fe_add(inner, inner, one); /* u^2 + Au + 1 */
fe_mul.fe_mul(v2, u, inner); /* u(u^2 + Au + 1) */
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.whispersystems.curve25519.java;

public class fe_montx_to_edy {
public static void fe_montx_to_edy(int[] y, int[] u)
{
/*
y = (u - 1) / (u + 1)

NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp
*/
int[] one = new int[10], um1 = new int[10], up1 = new int[10];

fe_1.fe_1(one);
fe_sub.fe_sub(um1, u, one);
fe_add.fe_add(up1, u, one);
fe_invert.fe_invert(up1, up1);
fe_mul.fe_mul(y, um1, up1);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.whispersystems.curve25519.java;

public class fe_sqrt {

/* sqrt(-1) */
public static byte[] i_bytes = {
(byte)0xb0, (byte)0xa0, 0x0e, 0x4a, 0x27, 0x1b, (byte)0xee, (byte)0xc4,
0x78, (byte)0xe4, 0x2f, (byte)0xad, 0x06, 0x18, 0x43, 0x2f,
(byte)0xa7, (byte)0xd7, (byte)0xfb, 0x3d, (byte)0x99, 0x00, 0x4d, 0x2b,
0x0b, (byte)0xdf, (byte)0xc1, 0x4f, (byte)0x80, 0x24, (byte)0x83, 0x2b
};

/* Preconditions: a is square or zero */

public static void fe_sqrt(int[] out, int[] a)
{
int[] exp = new int[10], b = new int[10], b2 = new int[10], bi = new int[10], i = new int[10];

fe_frombytes.fe_frombytes(i, i_bytes);
fe_pow22523.fe_pow22523(exp, a); /* b = a^(q-5)/8 */


fe_mul.fe_mul(b, a, exp); /* b = a * a^(q-5)/8 */
fe_sq.fe_sq(b2, b); /* b^2 = a * a^(q-1)/4 */

/* note b^4 == a^2, so b^2 == a or -a
* if b^2 != a, multiply it by sqrt(-1) */
fe_mul.fe_mul(bi, b, i);
fe_cmov.fe_cmov(b, bi, 1 ^ fe_isequal.fe_isequal(b2, a));
fe_copy.fe_copy(out, b);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.whispersystems.curve25519.java;

public class ge_isneutral {
/*
return 1 if p is the neutral point
return 0 otherwise
*/

public static boolean ge_isneutral(ge_p3 p)
{
int[] zero = new int[10];
fe_0.fe_0(zero);

/* Check if p == neutral element == (0, 1) */
return (fe_isequal.fe_isequal(p.X, zero) & fe_isequal.fe_isequal(p.Y, p.Z)) == 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.whispersystems.curve25519.java;

public class ge_montx_to_p3 {
/* sqrt(-(A+2)) */
private static byte[] A_bytes = {
0x06, 0x7e, 0x45, (byte)0xff, (byte)0xaa, 0x04, 0x6e, (byte)0xcc,
(byte)0x82, 0x1a, 0x7d, 0x4b, (byte)0xd1, (byte)0xd3, (byte)0xa1, (byte)0xc5,
0x7e, 0x4f, (byte)0xfc, 0x03, (byte)0xdc, 0x08, 0x7b, (byte)0xd2,
(byte)0xbb, 0x06, (byte)0xa0, 0x60, (byte)0xf4, (byte)0xed, 0x26, 0x0f
};

public static void ge_montx_to_p3(ge_p3 p, int[] u, byte ed_sign_bit)
{
int[] x = new int[10], y = new int[10], A = new int[10], v = new int[10], v2 = new int[10], iv = new int[10], nx = new int[10];

fe_frombytes.fe_frombytes(A, A_bytes);

/* given u, recover edwards y */
/* given u, recover v */
/* given u and v, recover edwards gen_x */

fe_montx_to_edy.fe_montx_to_edy(y, u); /* y = (u - 1) / (u + 1) */

fe_mont_rhs.fe_mont_rhs(v2, u); /* v^2 = u(u^2 + Au + 1) */
fe_sqrt.fe_sqrt(v, v2); /* v = sqrt(v^2) */

fe_mul.fe_mul(x, u, A); /* gen_x = u * sqrt(-(A+2)) */
fe_invert.fe_invert(iv, v); /* 1/v */
fe_mul.fe_mul(x, x, iv); /* gen_x = (u/v) * sqrt(-(A+2)) */

fe_neg.fe_neg(nx, x); /* negate gen_x to match sign bit */
fe_cmov.fe_cmov(x, nx, fe_isnegative.fe_isnegative(x) ^ ed_sign_bit);

fe_copy.fe_copy(p.X, x);
fe_copy.fe_copy(p.Y, y);
fe_1.fe_1(p.Z);
fe_mul.fe_mul(p.T, p.X, p.Y);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.whispersystems.curve25519.java;

public class ge_neg {
public static void ge_neg(ge_p3 r, ge_p3 p)
{
fe_neg.fe_neg(r.X, p.X);
fe_copy.fe_copy(r.Y, p.Y);
fe_copy.fe_copy(r.Z, p.Z);
fe_neg.fe_neg(r.T, p.T);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.whispersystems.curve25519.java;

public class ge_p3_add {
public static void ge_p3_add(ge_p3 r, ge_p3 p, ge_p3 q)
{
ge_cached p_cached = new ge_cached();
ge_p1p1 r_p1p1 = new ge_p1p1();

ge_p3_to_cached.ge_p3_to_cached(p_cached, p);
ge_add.ge_add(r_p1p1, q, p_cached);
ge_p1p1_to_p3.ge_p1p1_to_p3(r, r_p1p1);
}

}
Loading