public static int crypto_vsign_open_modified(ISha512 sha512provider,
                                                     byte[] m,
                                                     byte[] sm, long smlen,
                                                     byte[] pk, Ge_p3 Bv)
        {
            Ge_p3 Vneg   = new Ge_p3();
            Ge_p3 V      = new Ge_p3();
            Ge_p3 Aneg   = new Ge_p3();
            Ge_p3 A      = new Ge_p3();
            Ge_p3 c_V    = new Ge_p3();
            Ge_p3 c_A    = new Ge_p3();
            Ge_p3 h_Vneg = new Ge_p3();
            Ge_p3 s_Bv   = new Ge_p3();

            byte[] h = new byte[32];
            byte[] s = new byte[32];
            Ge_p2  R = new Ge_p2();

            byte[] hcheck     = new byte[64];
            byte[] vrf_output = 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(Aneg, pk) != 0)
            {
                return(-1);
            }

            /* Load -V, h, s */
            if (Ge_frombytes.ge_frombytes_negate_vartime(Vneg, sm) != 0)
            {
                return(-1);
            }
            Array.Copy(sm, 32, h, 0, 32);
            Array.Copy(sm, 64, s, 0, 32);
            if ((h[31] & 224) != 0) /* strict parsing of h */
            {
                return(-1);
            }
            if ((s[31] & 224) != 0) /* strict parsing of s */
            {
                return(-1);
            }

            Ge_neg.ge_neg(A, Aneg);
            Ge_neg.ge_neg(V, Vneg);
            Ge_scalarmult_cofactor.ge_scalarmult_cofactor(c_A, A);
            Ge_scalarmult_cofactor.ge_scalarmult_cofactor(c_V, V);
            if (Ge_isneutral.ge_isneutral(c_A) != 0 ||
                Ge_isneutral.ge_isneutral(c_V) != 0 ||
                Ge_isneutral.ge_isneutral(Bv) != 0)
            {
                return(-1);
            }

            // R = (s*B) + (h * -A))
            Ge_double_scalarmult.ge_double_scalarmult_vartime(R, h, Aneg, s);

            // s * Bv
            Ge_scalarmult.ge_scalarmult(s_Bv, s, Bv);

            // h * -V
            Ge_scalarmult.ge_scalarmult(h_Vneg, h, Vneg);

            // Rv = (sc * Bv) + (hc * (-V))
            Ge_p1p1   Rp1p1        = new Ge_p1p1();
            Ge_p3     Rv           = new Ge_p3();
            Ge_cached h_Vnegcached = new Ge_cached();

            Ge_p3_to_cached.ge_p3_to_cached(h_Vnegcached, h_Vneg);
            Ge_add.ge_add(Rp1p1, s_Bv, h_Vnegcached);
            Ge_p1p1_to_p3.ge_p1p1_to_p3(Rv, Rp1p1);

            // Check h == SHA512(label(4) || A || V || R || Rv || M)
            m[0] = 0xFB; // label 4
            for (count = 1; count < 32; count++)
            {
                m[count] = 0xFF;
            }
            Array.Copy(pk, 0, m, 32, 32);
            byte[] M = new byte[32];
            Array.Copy(m, 64, M, 0, 32);
            Ge_p3_tobytes.ge_p3_tobytes(M, V);
            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, Rv);
            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)
            {
                byte[] M4 = new byte[32];
                Array.Copy(m, 32, M4, 0, 32);
                Ge_p3_tobytes.ge_p3_tobytes(M4, c_V);
                Array.Copy(M4, 0, m, 32, 32);
                m[0] = 0xFA; // label 5
                sha512provider.calculateDigest(vrf_output, m, 64);
                Array.Copy(vrf_output, 0, m, 0, 32);
                return(0);
            }

            //badsig
            //memset(m, 0, 32);
            return(-1);
        }
Example #2
0
        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);
        }