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 */ }
public static int crypto_usign_open_modified(ISha512 sha512provider, byte[] m, long mlen, byte[] sm, long smlen, byte[] pk, Ge_p3 Bu) { Ge_p3 U = new Ge_p3(); byte[] h = new byte[64]; byte[] s = new byte[64]; byte[] strict = new byte[64]; Ge_p3 A = new Ge_p3(); Ge_p2 R = new Ge_p2(); byte[] hcheck = new byte[64]; int count; if (smlen < 96) { return(-1); } if ((sm[63] & 224) != 0) /* strict parsing of h */ { return(-1); } if ((sm[95] & 224) != 0) /* strict parsing of s */ { return(-1); } /* Load -A */ if (Ge_frombytes.ge_frombytes_negate_vartime(A, pk) != 0) { return(-1); } /* Load -U, h, s */ Ge_frombytes.ge_frombytes_negate_vartime(U, sm); Array.Copy(sm, 32, h, 0, 32); Array.Copy(sm, 64, s, 0, 32); /* Insist that s and h are reduced scalars (strict parsing) */ Array.Copy(h, 0, strict, 0, 64); Sc_reduce.sc_reduce(strict); if (!Arrays.isEqual(strict, h, 32)) { return(-1); } Array.Copy(s, 0, strict, 0, 64); Sc_reduce.sc_reduce(strict); if (!Arrays.isEqual(strict, s, 32)) { return(-1); } /* Reject U (actually -U) if small order */ if (Ge_is_small_order.ge_is_small_order(U) != 0) { return(-1); } // R = sB + h(-A) Ge_double_scalarmult.ge_double_scalarmult_vartime(R, h, A, s); // Ru = sBu + h(-U) Ge_p3 sBu = new Ge_p3(); Ge_p3 hU = new Ge_p3(); // sBu Ge_scalarmult.ge_scalarmult(sBu, s, Bu); // h(-U) Ge_scalarmult.ge_scalarmult(hU, h, U); // Ru = sBu + h(-U) Ge_p1p1 Rp1p1 = new Ge_p1p1(); Ge_p3 Ru = new Ge_p3(); Ge_cached hUcached = new Ge_cached(); Ge_p3_to_cached.ge_p3_to_cached(hUcached, hU); Ge_add.ge_add(Rp1p1, sBu, hUcached); Ge_p1p1_to_p3.ge_p1p1_to_p3(Ru, Rp1p1); // Check h == SHA512(label(4) || A || U || R || Ru || M) m[0] = 0xFB; for (count = 1; count < 32; count++) { m[count] = 0xFF; } Array.Copy(pk, 0, m, 32, 32); /* undo the negation for U */ Fe_neg.fe_neg(U.X, U.X); Fe_neg.fe_neg(U.T, U.T); byte[] M = new byte[32]; Array.Copy(m, 64, M, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M, U); Array.Copy(M, 0, m, 64, 32); byte[] M2 = new byte[32]; Array.Copy(m, 96, M2, 0, 32); Ge_tobytes.ge_tobytes(M2, R); Array.Copy(M2, 0, m, 96, 32); byte[] M3 = new byte[32]; Array.Copy(m, 128, M3, 0, 32); Ge_p3_tobytes.ge_p3_tobytes(M3, Ru); Array.Copy(M3, 0, m, 128, 32); Array.Copy(sm, 96, m, 160, (int)smlen - 96); sha512provider.calculateDigest(hcheck, m, smlen + 64); Sc_reduce.sc_reduce(hcheck); if (Crypto_verify_32.crypto_verify_32(hcheck, h) == 0) { Array.Copy(m, 64, m, 0, (int)smlen - 64); //memset(m + smlen - 64,0,64); //*mlen = smlen - 64; return(0); } //badsig: //*mlen = -1; //memset(m,0,smlen); return(-1); }