Ejemplo n.º 1
0
        public override byte[] Sign(byte[] publicKey, byte[] privateKey, byte[] M, byte[] context = null)
        {
            ShakeDigest sha512 = new ShakeDigest(256);

            sha512.BlockUpdate(privateKey, 0, privateKey.Length);
            byte[] h = new byte[114];
            sha512.DoFinal(h, 0, 114);
            byte[] x = new byte[57];
            Array.Copy(h, x, 57);
            x[0]  &= 0xfc; // Clear lowest 2 bits
            x[56]  = 0;    // Clear the highest byte
            x[55] |= 0x80; // Set the highest bit
            Array.Reverse(x);
            BigInteger a = new BigInteger(1, x);

            byte[] A = publicKey;

            byte[] prefix = new byte[57];
            Array.Copy(h, 57, prefix, 0, 57);

            M = PreHash(M);

            sha512.Reset();
            byte[] domBytes = Dom(context);
            sha512.BlockUpdate(domBytes, 0, domBytes.Length);
            sha512.BlockUpdate(prefix, 0, prefix.Length);
            sha512.BlockUpdate(M, 0, M.Length);
            byte[] r1 = new byte[114];
            sha512.DoFinal(r1, 0, 114);
            Array.Reverse(r1);
            BigInteger r  = new BigInteger(1, r1).Mod(EdDSAPoint448.L);
            EdDSAPoint rB = EdDSAPoint448.B.MultipleByScalar(r);

            byte[] R = rB.Encode();

            sha512.Reset();
            sha512.BlockUpdate(domBytes, 0, domBytes.Length);
            sha512.BlockUpdate(R, 0, R.Length);
            sha512.BlockUpdate(A, 0, A.Length);
            sha512.BlockUpdate(M, 0, M.Length);
            byte[] kBytes = new byte[114];
            sha512.DoFinal(kBytes, 0, 114);
            Array.Reverse(kBytes);
            BigInteger k = new BigInteger(1, kBytes).Mod(EdDSAPoint448.L);
            BigInteger S = r.Add(k.Multiply(a)).Mod(EdDSAPoint448.L);

            byte[] hash = new byte[57 * 2];
            byte[] rgbS = S.ToByteArrayUnsigned();
            Array.Copy(rgbS, 0, hash, 57 - rgbS.Length, rgbS.Length);
            Array.Reverse(hash);
            Array.Copy(R, hash, 57);

            return(hash);
        }