public static void curve25519_keygen(byte[] curve25519_pubkey_out, byte[] curve25519_privkey_in) { Ge_p3 ed = new Ge_p3(); /* Ed25519 pubkey point */ int[] ed_y = new int[10]; int[] ed_y_plus_one = new int[10]; int[] one_minus_ed_y = new int[10]; int[] inv_one_minus_ed_y = new int[10]; int[] mont_x = new int[10]; /* Perform a fixed-base multiplication of the Edwards base point, * (which is efficient due to precalculated tables), then convert * to the Curve25519 montgomery-format public key. In particular, * convert Curve25519's "montgomery" x-coordinate into an Ed25519 * "edwards" y-coordinate: * * mont_x = (ed_y + 1) / (1 - ed_y) * * with projective coordinates: * * mont_x = (ed_y + ed_z) / (ed_z - ed_y) * * NOTE: ed_y=1 is converted to mont_x=0 since fe_invert is mod-exp */ Ge_scalarmult_base.ge_scalarmult_base(ed, curve25519_privkey_in); Fe_add.fe_add(ed_y_plus_one, ed.Y, ed.Z); Fe_sub.fe_sub(one_minus_ed_y, ed.Z, ed.Y); Fe_invert.fe_invert(inv_one_minus_ed_y, one_minus_ed_y); Fe_mul.fe_mul(mont_x, ed_y_plus_one, inv_one_minus_ed_y); Fe_tobytes.fe_tobytes(curve25519_pubkey_out, mont_x); }
public static int curve25519_verify(ISha512 sha512provider, byte[] signature, byte[] curve25519_pubkey, byte[] msg, int msg_len) { int[] mont_x = new int[10]; int[] mont_x_minus_one = new int[10]; int[] mont_x_plus_one = new int[10]; int[] inv_mont_x_plus_one = new int[10]; int[] one = new int[10]; int[] ed_y = new int[10]; byte[] ed_pubkey = new byte[32]; long some_retval = 0; byte[] verifybuf = new byte[msg_len + 64]; /* working buffer */ byte[] verifybuf2 = new byte[msg_len + 64]; /* working buffer #2 */ /* Convert the Curve25519 public key into an Ed25519 public key. In * particular, convert Curve25519's "montgomery" x-coordinate into an * Ed25519 "edwards" y-coordinate: * * ed_y = (mont_x - 1) / (mont_x + 1) * * NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp * * Then move the sign bit into the pubkey from the signature. */ Fe_frombytes.fe_frombytes(mont_x, curve25519_pubkey); Fe_1.fe_1(one); Fe_sub.fe_sub(mont_x_minus_one, mont_x, one); Fe_add.fe_add(mont_x_plus_one, mont_x, one); Fe_invert.fe_invert(inv_mont_x_plus_one, mont_x_plus_one); Fe_mul.fe_mul(ed_y, mont_x_minus_one, inv_mont_x_plus_one); Fe_tobytes.fe_tobytes(ed_pubkey, ed_y); /* Copy the sign bit, and remove it from signature */ ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ ed_pubkey[31] |= (byte)(signature[63] & 0x80); Array.Copy(signature, 0, verifybuf, 0, 64); verifybuf[63] &= 0x7F; Array.Copy(msg, 0, verifybuf, 64, (int)msg_len); /* Then perform a normal Ed25519 verification, return 0 on success */ /* The below call has a strange API: */ /* verifybuf = R || S || message */ /* verifybuf2 = java to next call gets a copy of verifybuf, S gets * replaced with pubkey for hashing, then the whole thing gets zeroized * (if bad sig), or contains a copy of msg (good sig) */ return(Open.crypto_sign_open(sha512provider, verifybuf2, some_retval, verifybuf, 64 + msg_len, ed_pubkey)); }
public static void elligator(int[] u, int[] r) { /* r = input * x = -A/(1+2r^2) # 2 is nonsquare * e = (x^3 + Ax^2 + x)^((q-1)/2) # legendre symbol * if e == 1 (square) or e == 0 (because x == 0 and 2r^2 + 1 == 0) * u = x * if e == -1 (nonsquare) * u = -x - A */ int[] A = new int[10]; int[] one = new int[10]; int[] twor2 = new int[10]; int[] twor2plus1 = new int[10]; int[] twor2plus1inv = new int[10]; int[] x = new int[10]; int[] e = new int[10]; int[] Atemp = new int[10]; int[] 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); /* x = -A/(1+2r^2) */ Fe_mont_rhs.fe_mont_rhs(e, x); /* e = x^3 + Ax^2 + 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); /* x, or x+A if nonsquare */ Fe_neg.fe_neg(uneg, u); /* -x, or -x-A if nonsquare */ Fe_cmov.fe_cmov(u, uneg, nonsquare); /* x, or -x-A if nonsquare */ }