Пример #1
0
        public void EncryptDecryptNBlocksTest()
        {
            // Arrange
            var rnd = new Random();
            var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];

            for (var i = 0; i < 64; i++)
            {
                rnd.NextBytes(key);

                var cipher = new ChaCha20(key, 0);

                for (var j = 0; j < 64; j++)
                {
                    var expectedInput = new byte[rnd.Next(300)];
                    rnd.NextBytes(expectedInput);

                    // Act
                    var output      = cipher.Encrypt(expectedInput);
                    var actualInput = cipher.Decrypt(output);

                    // Assert
                    //Assert.AreEqual(expectedInput, actualInput);
                    Assert.IsTrue(CryptoBytes.ConstantTimeEquals(expectedInput, actualInput));
                }
            }
        }
Пример #2
0
        public void ConstantTimeEqualsSegmentsMustHaveSameLength()
        {
            var x = new byte[5];
            var y = new byte[5];

            Assert.Throws <ArgumentException>(() => CryptoBytes.ConstantTimeEquals(new ArraySegment <byte>(x, 0, 4), new ArraySegment <byte>(y, 0, 5)));
        }
Пример #3
0
        public void ConstantTimeEqualsSegmentsSuccess()
        {
            var x = new byte[] { 1, 2, 3 };
            var y = new byte[] { 1, 2, 3 };

            Assert.IsTrue(CryptoBytes.ConstantTimeEquals(x.Pad(), y.Pad()));
        }
Пример #4
0
        public void EncryptDecryptLongMessagesWithNonceTest()
        {
            var rnd = new Random();

            var dataSize = 16;

            while (dataSize <= (1 << 24))
            {
                var plaintext = new byte[dataSize];
                rnd.NextBytes(plaintext);

                var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];
                rnd.NextBytes(key);

                var cipher = new XChaCha20(key, 0);

                var nonce = new byte[cipher.NonceSizeInBytes()];
                rnd.NextBytes(nonce);

                var ciphertext = cipher.Encrypt(plaintext, nonce);
                var decrypted  = cipher.Decrypt(ciphertext, nonce);

                //Assert.AreEqual(plaintext, decrypted);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(plaintext, decrypted));
                dataSize += 5 * dataSize / 11;
            }
        }
Пример #5
0
        public void EncryptDecryptLongMessagesWithNonceTest()
        {
            var rnd = new Random();

            var dataSize = 16;

            while (dataSize <= (1 << 24))
            {
                var plaintext = new byte[dataSize];
                rnd.NextBytes(plaintext);

                var aad = new byte[dataSize / 3];
                rnd.NextBytes(aad);

                var nonce = new byte[12];
                rnd.NextBytes(nonce);

                var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];
                rnd.NextBytes(key);

                var aead       = new ChaCha20Poly1305(key);
                var ciphertext = aead.Encrypt(plaintext, aad, nonce);
                var decrypted  = aead.Decrypt(ciphertext, aad, nonce);

                //Assert.AreEqual(plaintext, decrypted);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(plaintext, decrypted));
                dataSize += 5 * dataSize / 11;
            }
        }
Пример #6
0
        public void ConstantTimeEqualsSuccess()
        {
            var x = new byte[] { 1, 2, 3 };
            var y = new byte[] { 1, 2, 3 };

            Assert.IsTrue(CryptoBytes.ConstantTimeEquals(x, y));
        }
Пример #7
0
        public static bool crypto_sign_verify(ReadOnlySpan <byte> sig, ReadOnlySpan <byte> m, ReadOnlySpan <byte> pk)
        {
            if ((sig[63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.ge_frombytes_negate_vartime(out var A, pk) != 0)
            {
                return(false);
            }

            var hasher = new Sha512();

            hasher.Update(sig.Slice(0, 32));
            hasher.Update(pk.Slice(0, 32));
            hasher.Update(m);
            Span <byte> h = stackalloc byte[64];

            hasher.Finish(h);

            ScalarOperations.sc_reduce(h);

            GroupOperations.ge_double_scalarmult_vartime(out var R, h, in A, sig.Slice(32, 32));
            Span <byte> checkr = stackalloc byte[32];

            GroupOperations.ge_tobytes(checkr, in R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, sig, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checkr);
            return(result);
        }
Пример #8
0
        public void ConstantTimeEqualsSegmentsMustHaveSameLength()
        {
            var x = new byte[5];
            var y = new byte[5];

            CryptoBytes.ConstantTimeEquals(new ArraySegment <byte>(x, 0, 4), new ArraySegment <byte>(y, 0, 5));
        }
Пример #9
0
        public void EncryptDecryptWithNonceTest()
        {
            var rnd = new Random();
            var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];

            rnd.NextBytes(key);

            var aead = new ChaCha20Poly1305(key);

            for (var i = 0; i < 100; i++)
            {
                var message = new byte[100];
                rnd.NextBytes(message);

                var aad = new byte[16];
                rnd.NextBytes(aad);

                var nonce = new byte[12];
                rnd.NextBytes(nonce);

                var ciphertext = aead.Encrypt(message, aad, nonce);
                var decrypted  = aead.Decrypt(ciphertext, aad, nonce);

                //Assert.AreEqual(message, decrypted);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(message, decrypted));
            }
        }
Пример #10
0
        public void ConstantTimeEqualsSegmentsSuccess()
        {
            var x = new byte[] { 1, 2, 3 };
            var y = new byte[] { 1, 2, 3 };

            CryptoBytes.ConstantTimeEquals(x.Pad(), y.Pad()).Should().BeTrue();
        }
Пример #11
0
        public void ConstantTimeEqualsRangeSuccess()
        {
            var x       = new byte[] { 1, 2, 3 };
            var y       = new byte[] { 1, 2, 3 };
            var paddedX = x.Pad();
            var paddedY = y.Pad();

            Assert.IsTrue(CryptoBytes.ConstantTimeEquals(paddedX.Array, paddedX.Offset, paddedY.Array, paddedY.Offset, paddedX.Count));
        }
Пример #12
0
        public void ConstantTimeEqualsSegmentsFail()
        {
            var x = new byte[] { 1, 2, 3 };

            foreach (var y in x.WithChangedBit())
            {
                Assert.IsFalse(CryptoBytes.ConstantTimeEquals(x.Pad(), y.Pad()));
            }
        }
Пример #13
0
        public void ConstantTimeEqualsSegmentsMustHaveSameLength()
        {
            var x = new byte[5];
            var y = new byte[5];

            Action act = () => CryptoBytes.ConstantTimeEquals(new ArraySegment <byte>(x, 0, 4), new ArraySegment <byte>(y, 0, 5));

            act.Should().Throw <ArgumentException>();
        }
Пример #14
0
        public void ConstantTimeEqualsFail()
        {
            var x = new byte[] { 1, 2, 3 };

            foreach (var y in x.WithChangedBit())
            {
                CryptoBytes.ConstantTimeEquals(x, y).Should().BeFalse();
            }
        }
Пример #15
0
        public void ChaCha20TestVectorTC8()
        {
            // TC8: key: 'All your base are belong to us!, IV: 'IETF2013'
            // Test vector TC8 from RFC draft by J. Strombergson
            // https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01

            // Arrange
            var key = new byte[32]
            {
                0xC4, 0x6E, 0xC1, 0xB1, 0x8C, 0xE8, 0xA8, 0x78,
                0x72, 0x5A, 0x37, 0xE7, 0x80, 0xDF, 0xB7, 0x35,
                0x1F, 0x68, 0xED, 0x2E, 0x19, 0x4C, 0x79, 0xFB,
                0xC6, 0xAE, 0xBE, 0xE1, 0xA6, 0x67, 0x97, 0x5D
            };

            // The first 4 bytes are set to zero and a large counter
            // is used; this makes the RFC 8439 version of ChaCha20
            // compatible with the original specification by D. J. Bernstein.
            var nonce = new byte[12] {
                0x00, 0x00, 0x00, 0x00,
                0x1A, 0xDA, 0x31, 0xD5, 0xCF, 0x68, 0x82, 0x21
            };

            // Act
            var cipher = new ChaCha20(key, 0);
            var block0 = new byte[Snuffle.BLOCK_SIZE_IN_BYTES];
            var block1 = new byte[Snuffle.BLOCK_SIZE_IN_BYTES];

            cipher.ProcessKeyStreamBlock(nonce, 0, block0);
            cipher.ProcessKeyStreamBlock(nonce, 1, block1);

            // Assert
            var expected = new byte[128]
            {
                0xF6, 0x3A, 0x89, 0xB7, 0x5C, 0x22, 0x71, 0xF9,
                0x36, 0x88, 0x16, 0x54, 0x2B, 0xA5, 0x2F, 0x06,
                0xED, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2B, 0x00,
                0xB5, 0xE8, 0xF8, 0x0A, 0xE9, 0xA4, 0x73, 0xAF,
                0xC2, 0x5B, 0x21, 0x8F, 0x51, 0x9A, 0xF0, 0xFD,
                0xD4, 0x06, 0x36, 0x2E, 0x8D, 0x69, 0xDE, 0x7F,
                0x54, 0xC6, 0x04, 0xA6, 0xE0, 0x0F, 0x35, 0x3F,
                0x11, 0x0F, 0x77, 0x1B, 0xDC, 0xA8, 0xAB, 0x92,

                0xE5, 0xFB, 0xC3, 0x4E, 0x60, 0xA1, 0xD9, 0xA9,
                0xDB, 0x17, 0x34, 0x5B, 0x0A, 0x40, 0x27, 0x36,
                0x85, 0x3B, 0xF9, 0x10, 0xB0, 0x60, 0xBD, 0xF1,
                0xF8, 0x97, 0xB6, 0x29, 0x0F, 0x01, 0xD1, 0x38,
                0xAE, 0x2C, 0x4C, 0x90, 0x22, 0x5B, 0xA9, 0xEA,
                0x14, 0xD5, 0x18, 0xF5, 0x59, 0x29, 0xDE, 0xA0,
                0x98, 0xCA, 0x7A, 0x6C, 0xCF, 0xE6, 0x12, 0x27,
                0x05, 0x3C, 0x84, 0xE4, 0x9A, 0x4A, 0x33, 0x32
            };

            //Assert.AreEqual(expected, Combine(block0, block1));
            Assert.IsTrue(CryptoBytes.ConstantTimeEquals(expected, CryptoBytes.Combine(block0, block1)));
        }
Пример #16
0
        public void ConstantTimeEqualsRangeFail()
        {
            var x = new byte[] { 1, 2, 3 };

            foreach (var y in x.WithChangedBit())
            {
                var paddedX = x.Pad();
                var paddedY = y.Pad();
                Assert.IsFalse(CryptoBytes.ConstantTimeEquals(paddedX.Array, paddedX.Offset, paddedY.Array, paddedY.Offset, paddedX.Count));
            }
        }
Пример #17
0
        /// <summary>
        /// Verifies the authentication <paramref name="mac"> using the specified <paramref name="key"> and <paramref name="data">.
        /// </summary>
        /// <param name="key">The secret key.</param>
        /// <param name="data">The data.</param>
        /// <param name="mac">The authentication tag.</param>
        /// <exception cref="CryptographicException"></exception>
        public static void VerifyMac(ReadOnlySpan <byte> key, ReadOnlySpan <byte> data, ReadOnlySpan <byte> mac)
        {
            Span <byte> tag = stackalloc byte[MAC_TAG_SIZE_IN_BYTES];

            ComputeMac(key, data, tag);

            if (!CryptoBytes.ConstantTimeEquals(tag, mac))
            {
                throw new CryptographicException(MAC_EXCEPTION_INVALID);
            }
        }
Пример #18
0
        // Original crypto_sign_open, for reference only

        /*public static int crypto_sign_open(
         * byte[] m, out int mlen,
         * byte[] sm, int smlen,
         * byte[] pk)
         * {
         *  byte[] h = new byte[64];
         *  byte[] checkr = new byte[32];
         *  GroupElementP3 A;
         *  GroupElementP2 R;
         *  int i;
         *
         *  mlen = -1;
         *  if (smlen < 64) return -1;
         *  if ((sm[63] & 224) != 0) return -1;
         *  if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, 0) != 0) return -1;
         *
         *  for (i = 0; i < smlen; ++i) m[i] = sm[i];
         *  for (i = 0; i < 32; ++i) m[32 + i] = pk[i];
         *  Sha512BclWrapper.crypto_hash_sha512(h, m, 0, smlen);
         *  ScalarOperations.sc_reduce(h);
         *
         *  var sm32 = new byte[32];
         *  Array.Copy(sm, 32, sm32, 0, 32);
         *  GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
         *  GroupOperations.ge_tobytes(checkr, 0, ref R);
         *  if (Helpers.crypto_verify_32(checkr, sm) != 0)
         *  {
         *      for (i = 0; i < smlen; ++i)
         *          m[i] = 0;
         *      return -1;
         *  }
         *
         *  for (i = 0; i < smlen - 64; ++i)
         *      m[i] = sm[64 + i];
         *  for (i = smlen - 64; i < smlen; ++i)
         *      m[i] = 0;
         *  mlen = smlen - 64;
         *  return 0;
         * }*/

        public static bool crypto_sign_verify(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] pk, int pkoffset)
        {
            byte[]         h;
            byte[]         checkr = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((sig[sigoffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, pkoffset) != 0)
            {
                return(false);
            }

            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(sig, sigoffset, 32);
            hasher.Update(pk, pkoffset, 32);
            hasher.Update(m, moffset, mlen);
            h = hasher.Finish();

            /*
             * var hasher = new Sha512();
             * hasher.Update(sig, sigoffset, 32);
             * hasher.Update(pk, pkoffset, 32);
             * hasher.Update(m, moffset, mlen);
             * h = hasher.Finish();
             */

            ScalarOperations.sc_reduce(h);

            var sm32 = new byte[32];//todo: remove allocation

            Array.Copy(sig, sigoffset + 32, sm32, 0, 32);
            GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
            GroupOperations.ge_tobytes(checkr, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, 0, sig, sigoffset, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checkr);
            return(result);
        }
Пример #19
0
        public void HChaCha20TestVectors()
        {
            // Arrange
            foreach (var test in HChaCha20TestVector.HChaCha20TestVectors)
            {
                var cipher = new XChaCha20(test.Key, 0);

                // Act
                var output = cipher.HChaCha20(test.Input);

                // Assert
                //Assert.That(output, Is.EqualTo(test.Output));
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(test.Output, output));
            }
        }
Пример #20
0
        /// <summary>
        /// Verifies the authentication <paramref name="mac"/> using the specified <paramref name="key"/> and <paramref name="data"/>.
        /// </summary>
        /// <param name="key">The secret key.</param>
        /// <param name="data">The data.</param>
        /// <param name="tag">The authentication tag.</param>
        /// <exception cref="CryptographicException"></exception>
        public static void VerifyMac(ReadOnlySpan <byte> key, ReadOnlySpan <byte> data, ReadOnlySpan <byte> tag)
        {
            if (tag.Length != MAC_TAG_SIZE_IN_BYTES)
            {
                throw new CryptographicException($"The tag length in bytes must be {MAC_TAG_SIZE_IN_BYTES}.");
            }

            Span <byte> mac = stackalloc byte[MAC_TAG_SIZE_IN_BYTES];

            ComputeMac(key, data, mac);

            if (!CryptoBytes.ConstantTimeEquals(mac, tag))
            {
                throw new CryptographicException(MAC_EXCEPTION_INVALID);
            }
        }
Пример #21
0
        public void ChaCha20TestVector()
        {
            // https://tools.ietf.org/html/rfc8439#section-2.4.2

            // Arrange
            foreach (var test in Rfc8439TestVector.Rfc8439TestVectors)
            {
                // Act
                var cipher = new ChaCha20(test.Key, test.InitialCounter);
                var output = cipher.Decrypt(CryptoBytes.Combine(test.Nonce, test.CipherText));

                // Assert
                //Assert.That(output, Is.EqualTo(test.PlainText));
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(test.PlainText, output));
            }
        }
Пример #22
0
        public void XChaCha20TestVectors()
        {
            // From libsodium's test/default/xchacha20.c (tv_stream_xchacha20) and https://tools.ietf.org/html/draft-arciszewski-xchacha-00.

            // Arrange
            foreach (var test in XChaCha20TestVector.XChaCha20TestVectors)
            {
                // Act
                var cipher = new XChaCha20(test.Key, 0);
                var output = cipher.Decrypt(CryptoBytes.Combine(test.Nonce, test.CipherText));

                // Assert
                //Assert.That(output, Is.EqualTo(test.Output));
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(test.PlainText, output));
            }
        }
Пример #23
0
        public void XChaCha20Poly1305TestVectors()
        {
            // From libsodium's test/default/aead_xchacha20poly1305.c and https://tools.ietf.org/html/draft-arciszewski-xchacha-01.

            // Arrange
            foreach (var test in XChaCha20Poly1305TestVector.TestVectors)
            {
                // Act
                var aead = new XChaCha20Poly1305(test.Key);

                //var message = aead.Decrypt(CryptoBytes.Combine(test.CipherText, test.Tag), test.Aad, test.Nonce); // same as below...
                var output = aead.Decrypt(CryptoBytes.Combine(test.Nonce, test.CipherText, test.Tag), test.Aad);

                // Assert
                //Assert.That(output, Is.EqualTo(test.PlainText));
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(test.PlainText, output));
            }
        }
Пример #24
0
        public void ChaCha20Poly1305TestVector2()
        {
            // https://tools.ietf.org/html/rfc8439

            // Arrange
            foreach (var test in Rfc8439TestVector.Rfc7634AeadTestVectors)
            {
                // Act
                var aead = new ChaCha20Poly1305(test.Key);
                var ct   = aead.Encrypt(test.PlainText, test.Aad, test.Nonce);
                Assert.That(ct, Is.EqualTo(CryptoBytes.Combine(test.CipherText, test.Tag)));

                var output = aead.Decrypt(ct, test.Aad, test.Nonce);

                // Assert
                //Assert.That(output, Is.EqualTo(test.PlainText));
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(test.PlainText, output));
            }
        }
Пример #25
0
        public void EncryptDecrypt1BlockTest()
        {
            // Arrange
            var rnd = new Random();
            var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];

            rnd.NextBytes(key);

            var expectedInput = Encoding.UTF8.GetBytes("Hello World!!");

            var cipher = new ChaCha20(key, 0);

            // Act
            var output      = cipher.Encrypt(expectedInput);
            var actualInput = cipher.Decrypt(output);

            // Assert
            //Assert.AreEqual(expectedInput, actualInput);
            Assert.IsTrue(CryptoBytes.ConstantTimeEquals(expectedInput, actualInput));
        }
Пример #26
0
        public void ModifiedAssociatedDataFails()
        {
            var rnd = new Random();
            var key = new byte[Snuffle.KEY_SIZE_IN_BYTES];

            rnd.NextBytes(key);

            var aead = new ChaCha20Poly1305(key);
            var aad  = new byte[0];

            for (var msgSize = 0; msgSize < 75; msgSize++)
            {
                var message = new byte[msgSize];
                rnd.NextBytes(message);

                // encrypting with aad as a 0-length array
                var ciphertext = aead.Encrypt(message, aad);
                var decrypted  = aead.Decrypt(ciphertext, aad);
                //Assert.AreEqual(message, decrypted);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(message, decrypted));

                var decrypted2 = aead.Decrypt(ciphertext, null);
                //Assert.AreEqual(message, decrypted2);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(message, decrypted2));

                var badAad = new byte[] { 1, 2, 3 };
                Assert.Throws <CryptographicException>(() => aead.Decrypt(ciphertext, badAad), SnufflePoly1305.AEAD_EXCEPTION_INVALID_TAG);

                // encrypting with aad equal to null
                ciphertext = aead.Encrypt(message, null);
                decrypted  = aead.Decrypt(ciphertext, aad);
                //Assert.AreEqual(message, decrypted);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(message, decrypted));

                decrypted2 = aead.Decrypt(ciphertext, null);
                //Assert.AreEqual(message, decrypted2);
                Assert.IsTrue(CryptoBytes.ConstantTimeEquals(message, decrypted2));

                Assert.Throws <CryptographicException>(() => aead.Decrypt(ciphertext, badAad), SnufflePoly1305.AEAD_EXCEPTION_INVALID_TAG);
            }
        }
Пример #27
0
        // Original crypto_sign_open, for reference only

        /*public static int crypto_sign_open(
         * byte[] m, out int mlen,
         * byte[] sm, int smlen,
         * byte[] pk)
         * {
         *  byte[] h = new byte[64];
         *  byte[] checkr = new byte[32];
         *  GroupElementP3 A;
         *  GroupElementP2 R;
         *  int i;
         *
         *  mlen = -1;
         *  if (smlen < 64) return -1;
         *  if ((sm[63] & 224) != 0) return -1;
         *  if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, 0) != 0) return -1;
         *
         *  for (i = 0; i < smlen; ++i) m[i] = sm[i];
         *  for (i = 0; i < 32; ++i) m[32 + i] = pk[i];
         *  Sha512BclWrapper.crypto_hash_sha512(h, m, 0, smlen);
         *  ScalarOperations.sc_reduce(h);
         *
         *  var sm32 = new byte[32];
         *  Array.Copy(sm, 32, sm32, 0, 32);
         *  GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
         *  GroupOperations.ge_tobytes(checkr, 0, ref R);
         *  if (Helpers.crypto_verify_32(checkr, sm) != 0)
         *  {
         *      for (i = 0; i < smlen; ++i)
         *          m[i] = 0;
         *      return -1;
         *  }
         *
         *  for (i = 0; i < smlen - 64; ++i)
         *      m[i] = sm[64 + i];
         *  for (i = smlen - 64; i < smlen; ++i)
         *      m[i] = 0;
         *  mlen = smlen - 64;
         *  return 0;
         * }*/

        public static bool crypto_sign_verify(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] pk, int pkoffset)
        {
            byte[]         checkr = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((sig[sigoffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, pkoffset) != 0)
            {
                return(false);
            }
            var hash = new KeccakDigest(512);

            hash.BlockUpdate(sig, sigoffset, 32);
            hash.BlockUpdate(pk, pkoffset, 32);
            hash.BlockUpdate(m, moffset, mlen);
            var b = new byte[64];

            hash.DoFinal(b, 0);


            ScalarOperations.sc_reduce(b);

            var sm32 = new byte[32];//todo: remove allocation

            Array.Copy(sig, sigoffset + 32, sm32, 0, 32);
            GroupOperations.ge_double_scalarmult_vartime(out R, b, ref A, sm32);
            GroupOperations.ge_tobytes(checkr, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, 0, sig, sigoffset, 32);

            CryptoBytes.Wipe(b);
            CryptoBytes.Wipe(checkr);
            return(result);
        }
Пример #28
0
        public static bool crypto_sign_verify(
            byte[] signature, int signatureOffset,
            byte[] message, int messageOffset, int messageLength,
            byte[] publicKey, int publicKeyOffset)
        {
            byte[]         h;
            byte[]         checkr = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((signature[signatureOffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.ge_frombytes_negate_vartime(out A, publicKey, publicKeyOffset) != 0)
            {
                return(false);
            }

            var hasher = new Sha512();

            hasher.Update(signature, signatureOffset, 32);
            hasher.Update(publicKey, publicKeyOffset, 32);
            hasher.Update(message, messageOffset, messageLength);
            h = hasher.FinalizeHash();

            ScalarOperations.sc_reduce(h);

            var sm32 = new byte[32];//todo: remove allocation

            Array.Copy(signature, signatureOffset + 32, sm32, 0, 32);
            GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
            GroupOperations.ge_tobytes(checkr, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, 0, signature, signatureOffset, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checkr);
            return(result);
        }
Пример #29
0
        public static bool CryptoSignVerify(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] pk, int pkoffset)
        {
            var            checker = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((sig[sigoffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (GroupOperations.FromBytes(out A, pk, pkoffset) != 0)
            {
                return(false);
            }

            var hasher = new Sha512();

            hasher.Update(sig, sigoffset, 32);
            hasher.Update(pk, pkoffset, 32);
            hasher.Update(m, moffset, mlen);
            var h = hasher.Finalize();

            ScalarOperations.Reduce(h);

            var sm32 = new byte[32];

            Array.Copy(sig, sigoffset + 32, sm32, 0, 32);
            GroupOperations.DoubleScalarMult(out R, h, ref A, sm32);
            GroupOperations.ToBytes(checker, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checker, 0, sig, sigoffset, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checker);
            return(result);
        }
Пример #30
0
        // Original crypto_sign_open, for reference only

        /*public static int crypto_sign_open(
         * byte[] m, out int mlen,
         * byte[] sm, int smlen,
         * byte[] pk)
         * {
         *  byte[] h = new byte[64];
         *  byte[] checkr = new byte[32];
         *  GroupElementP3 A;
         *  GroupElementP2 R;
         *  int i;
         *
         *  mlen = -1;
         *  if (smlen < 64) return -1;
         *  if ((sm[63] & 224) != 0) return -1;
         *  if (GroupOperations.ge_frombytes_negate_vartime(out A, pk, 0) != 0) return -1;
         *
         *  for (i = 0; i < smlen; ++i) m[i] = sm[i];
         *  for (i = 0; i < 32; ++i) m[32 + i] = pk[i];
         *  Sha512BclWrapper.crypto_hash_sha512(h, m, 0, smlen);
         *  ScalarOperations.sc_reduce(h);
         *
         *  var sm32 = new byte[32];
         *  Array.Copy(sm, 32, sm32, 0, 32);
         *  GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
         *  GroupOperations.ge_tobytes(checkr, 0, ref R);
         *  if (Helpers.crypto_verify_32(checkr, sm) != 0)
         *  {
         *      for (i = 0; i < smlen; ++i)
         *          m[i] = 0;
         *      return -1;
         *  }
         *
         *  for (i = 0; i < smlen - 64; ++i)
         *      m[i] = sm[64 + i];
         *  for (i = smlen - 64; i < smlen; ++i)
         *      m[i] = 0;
         *  mlen = smlen - 64;
         *  return 0;
         * }*/

        public static bool CryptoSignVerify(
            byte[] sig, int sigoffset,
            byte[] m, int moffset, int mlen,
            byte[] pk, int pkoffset)
        {
            var            checkr = new byte[32];
            GroupElementP3 A;
            GroupElementP2 R;

            if ((sig[sigoffset + 63] & 224) != 0)
            {
                return(false);
            }
            if (stellar_dotnet_sdk.chaos.nacl.Internal.Ed25519Ref10.GroupOperations.ge_frombytes_negate_vartime(out A, pk, pkoffset) != 0)
            {
                return(false);
            }

            var hasher = new Sha512();

            hasher.Update(sig, sigoffset, 32);
            hasher.Update(pk, pkoffset, 32);
            hasher.Update(m, moffset, mlen);
            var h = hasher.Finish();

            ScalarOperations.ScReduce(h);

            var sm32 = new byte[32]; //todo: remove allocation

            Array.Copy(sig, sigoffset + 32, sm32, 0, 32);
            stellar_dotnet_sdk.chaos.nacl.Internal.Ed25519Ref10.GroupOperations.ge_double_scalarmult_vartime(out R, h, ref A, sm32);
            stellar_dotnet_sdk.chaos.nacl.Internal.Ed25519Ref10.GroupOperations.GeToBytes(checkr, 0, ref R);
            var result = CryptoBytes.ConstantTimeEquals(checkr, 0, sig, sigoffset, 32);

            CryptoBytes.Wipe(h);
            CryptoBytes.Wipe(checkr);
            return(result);
        }