예제 #1
0
        public void AuthenticatedAesCngGcmMultiRoundTripTest()
        {
            byte[] plaintext          = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] plaintext2         = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] expectedCiphertext = new byte[]
            {
                0x54, 0x2d, 0x26, 0x15, 0x9c, 0xb3, 0x6e, 0x21, 0xd2, 0x58, 0xcf, 0x9c, 0x6e, 0xce, 0xfb, 0x5f,
                0x8c, 0x2a, 0xb8, 0x22, 0x4d, 0x6d, 0xd0, 0x02, 0x76, 0xd2, 0xab, 0x22, 0xa2, 0xd6, 0xee, 0x5b
            };
            byte[] expectedTag = new byte[] { 0xc1, 0x34, 0x38, 0x0b, 0xc3, 0x87, 0x7c, 0xf5, 0x2f, 0x3b, 0xa9, 0xfe, 0x3c, 0x69, 0x4b, 0x9f };
            byte[] key         = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
            byte[] iv          = new byte[] { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

            using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
            {
                gcm.CngMode = CngChainingMode.Gcm;
                gcm.Key     = key;
                gcm.IV      = iv;
                gcm.Tag     = expectedTag;

                // Encrypt
                byte[] ciphertext = null;
                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            // Push through two blocks and call final to get the tag.
                            cs.Write(plaintext, 0, plaintext.Length);
                            cs.Write(plaintext2, 0, plaintext2.Length);
                            cs.FlushFinalBlock();

                            ciphertext = ms.ToArray();

                            // Check if the ciphertext and tag are what are expected.
                            Assert.IsTrue(Util.CompareBytes(expectedCiphertext, ciphertext));
                            Assert.IsTrue(Util.CompareBytes(expectedTag, encryptor.GetTag()));
                        }

                // Decrypt
                using (MemoryStream ms = new MemoryStream())
                    using (ICryptoTransform decryptor = gcm.CreateDecryptor())
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(ciphertext, 0, ciphertext.Length / 2);
                            cs.Write(ciphertext, ciphertext.Length / 2, ciphertext.Length / 2);

                            cs.FlushFinalBlock();

                            byte[] decrypted = ms.ToArray();

                            // Compare the decrypted text to the initial ciphertext.
                            byte[] fullPlaintext = new byte[plaintext.Length + plaintext2.Length];
                            Array.Copy(plaintext, 0, fullPlaintext, 0, plaintext.Length);
                            Array.Copy(plaintext2, 0, fullPlaintext, plaintext.Length, plaintext2.Length);
                            Assert.IsTrue(Util.CompareBytes(fullPlaintext, decrypted));
                        }
            }
        }
예제 #2
0
        public void PBKDF2SHA512TestVector()
        {
            byte[] password           = Encoding.ASCII.GetBytes("mypassword");
            byte[] salt               = Encoding.ASCII.GetBytes("1234567890");
            byte[] derivedKeyExpected = { 0xb9, 0x1d, 0x6a, 0xac, 0xf4, 0xac, 0x55, 0x4c, 0x1c, 0xc2, 0x1b, 0xfb, 0xc4, 0x71, 0xea, 0xde, 0x24, 0x9a, 0x5e, 0x04, 0x00, 0x3c, 0x5f, 0x22, 0xbe, 0x5d, 0x2a, 0xff, 0xe6, 0x0c, 0x9c, 0xc7, 0xa2, 0x4f, 0x0b, 0x27, 0x42, 0x64, 0x68, 0x4b, 0x4f, 0xad, 0xb2, 0xa7, 0x5d, 0x37, 0xb6, 0x05, 0xc6, 0xbf, 0xc5, 0x33, 0xa1, 0x12, 0x3f, 0x41, 0x5f, 0x93, 0x46, 0x8f, 0xff, 0xde, 0x71, 0x97 };

            byte[] derviedKey = BCryptPBKDF2.ComputeHash(PBKDF2HashAlgorithm.SHA512, password, salt, ITERATION_COUNT);

            Assert.IsTrue(Util.CompareBytes(derviedKey, derivedKeyExpected));
        }
예제 #3
0
        public void PBKDF2SHA384TestVector()
        {
            byte[] password           = Encoding.ASCII.GetBytes("mypassword");
            byte[] salt               = Encoding.ASCII.GetBytes("1234567890");
            byte[] derivedKeyExpected = { 0x1c, 0xbe, 0x2f, 0x1d, 0x30, 0x8f, 0x38, 0x2c, 0x72, 0x77, 0x42, 0x5b, 0x8f, 0xe8, 0x85, 0x38, 0x75, 0xb0, 0x5c, 0xbd, 0xd9, 0x53, 0xbb, 0xf5, 0x6c, 0x77, 0xeb, 0x11, 0x91, 0x2e, 0x08, 0xc1, 0x78, 0x89, 0xa5, 0x46, 0x72, 0xcd, 0xfd, 0xa3, 0x4e, 0xc0, 0x56, 0xfc, 0x6a, 0xd4, 0x88, 0x12 };

            byte[] derviedKey = BCryptPBKDF2.ComputeHash(PBKDF2HashAlgorithm.SHA384, password, salt, ITERATION_COUNT);

            Assert.IsTrue(Util.CompareBytes(derviedKey, derivedKeyExpected));
        }
예제 #4
0
        public void PBKDF2SHA256TestVector()
        {
            byte[] password           = Encoding.ASCII.GetBytes("mypassword");
            byte[] salt               = Encoding.ASCII.GetBytes("1234567890");
            byte[] derivedKeyExpected = { 0x6c, 0xca, 0x73, 0xcd, 0xa2, 0x1a, 0x01, 0xf0, 0x99, 0xaf, 0x2c, 0x7d, 0x68, 0x54, 0x8c, 0x31, 0x09, 0x44, 0x8b, 0x65, 0xcf, 0x12, 0x1d, 0x40, 0x01, 0x98, 0x3d, 0x95, 0x98, 0xdc, 0x01, 0xda };

            byte[] derviedKey = BCryptPBKDF2.ComputeHash(PBKDF2HashAlgorithm.SHA256, password, salt, ITERATION_COUNT);

            Assert.IsTrue(Util.CompareBytes(derviedKey, derivedKeyExpected));
        }
예제 #5
0
        public void PBKDF2SHA1TestVector()
        {
            byte[] password           = Encoding.ASCII.GetBytes("mypassword");
            byte[] salt               = Encoding.ASCII.GetBytes("1234567890");
            byte[] derivedKeyExpected = { 0x19, 0x36, 0x45, 0xd3, 0x70, 0x87, 0x2f, 0x63, 0xd0, 0x95, 0x5d, 0xac, 0x3d, 0x2d, 0xc8, 0x53, 0x59, 0xb1, 0x82, 0x10 };

            byte[] derviedKey = BCryptPBKDF2.ComputeHash(PBKDF2HashAlgorithm.SHA1, password, salt, ITERATION_COUNT);

            Assert.IsTrue(Util.CompareBytes(derviedKey, derivedKeyExpected));
        }
        private void RunTestVector(GcmTestVector test)
        {
            // Encrypt the input
            byte[] ciphertext = null;
            using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
            {
                gcm.CngMode           = CngChainingMode.Gcm;
                gcm.Key               = test.Key;
                gcm.IV                = test.IVBytes;
                gcm.AuthenticatedData = test.AuthenticationData;

                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = gcm.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            if (test.Plaintext != null)
                            {
                                cs.Write(test.Plaintext, 0, test.Plaintext.Length);
                            }

                            cs.FlushFinalBlock();
                            ciphertext = ms.ToArray();

                            // Verify the produced tag is what we expected it to be
                            Assert.IsTrue(Util.CompareBytes(test.Tag, encryptor.GetTag()));
                        }
            }

            if (test.Ciphertext != null)
            {
                // Verify the ciphertext is what we expected it to be
                Assert.IsTrue(Util.CompareBytes(test.Ciphertext, ciphertext));

                // Round trip the data
                using (AuthenticatedAesCng gcm = new AuthenticatedAesCng())
                {
                    gcm.CngMode           = CngChainingMode.Gcm;
                    gcm.Key               = test.Key;
                    gcm.IV                = test.IVBytes;
                    gcm.AuthenticatedData = test.AuthenticationData;
                    gcm.Tag               = test.Tag;

                    using (MemoryStream ms = new MemoryStream())
                        using (CryptoStream cs = new CryptoStream(ms, gcm.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(test.Ciphertext, 0, test.Ciphertext.Length);
                            cs.FlushFinalBlock();

                            byte[] plaintext = ms.ToArray();
                            Assert.IsTrue(Util.CompareBytes(test.Plaintext, plaintext));
                        }
                }
            }
        }
예제 #7
0
        public void AuthenticatedAesCngUpdateModePreserveTagTest()
        {
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                byte[] originalTag = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
                aes.Tag = originalTag;

                // We just set the tag, so it should be valid
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Changing to the current mode should not reset the tag
                aes.CngMode = aes.CngMode;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Explicitly changing to GCM should not reset the tag
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Switching from GCM to CCM should not reset the tag
                aes.CngMode = CngChainingMode.Ccm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Switching from CCM back to GCM should not reset the tag
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(originalTag, aes.Tag));

                // Using a large tag size that both modes support should not cause a reset
                byte[] largeTag = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
                aes.CngMode = CngChainingMode.Ccm;
                aes.Tag     = largeTag;
                Assert.IsTrue(Util.CompareBytes(largeTag, aes.Tag));
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsTrue(Util.CompareBytes(largeTag, aes.Tag));

                // However, using a small tag size that is only supported in CCM should reset when we switch
                // to GCM
                byte[] smallTag = new byte[] { 0, 1, 2, 3 };
                aes.CngMode = CngChainingMode.Ccm;
                aes.Tag     = smallTag;
                Assert.IsTrue(Util.CompareBytes(smallTag, aes.Tag));
                aes.CngMode = CngChainingMode.Gcm;
                Assert.IsFalse(Util.CompareBytes(smallTag, aes.Tag));
            }
        }
예제 #8
0
        public void HMACSHA384CngTest()
        {
            using (RNGCng rng = new RNGCng())
            {
                byte[] key = new byte[128];
                rng.GetBytes(key);

                using (HMACSHA384 bclHmac = new HMACSHA384(key))
                    using (HMACSHA384Cng cngHmac = new HMACSHA384Cng(key))
                    {
                        for (int i = 0; i < 10; ++i)
                        {
                            byte[] data = new byte[2048];
                            rng.GetBytes(data);

                            byte[] bcl = bclHmac.ComputeHash(data);
                            byte[] cng = cngHmac.ComputeHash(data);

                            Assert.IsTrue(Util.CompareBytes(bcl, cng));
                        }
                    }
            }
        }
예제 #9
0
        public void AuthenticatedAesCngChainingTest()
        {
            byte[] plaintext         = new byte[20 * 1024];
            byte[] iv                = new byte[12];
            byte[] authenticatedData = new byte[1024];

            using (RNGCng rng = new RNGCng())
            {
                rng.GetBytes(plaintext);
                rng.GetBytes(iv);
                rng.GetBytes(authenticatedData);
            }

            foreach (CngChainingMode chainingMode in new CngChainingMode[] { CngChainingMode.Ccm, CngChainingMode.Gcm })
            {
                using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
                {
                    aes.AuthenticatedData = authenticatedData;
                    aes.CngMode           = chainingMode;
                    aes.IV = iv;

                    // Encrypt the whole block of data at once
                    byte[] wholeCiphertext = null;
                    byte[] wholeTag        = null;
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                    {
                        wholeCiphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
                        wholeTag        = encryptor.GetTag();
                    }

                    // Encrypt it in chunks
                    byte[] blockCiphertext = null;
                    byte[] blockTag        = null;
                    using (MemoryStream ms = new MemoryStream())
                        using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                            {
                                int chunkSize = 128;
                                for (int offset = 0; offset < plaintext.Length; offset += chunkSize)
                                {
                                    cs.Write(plaintext, offset, chunkSize);
                                }
                                cs.FlushFinalBlock();

                                blockCiphertext = ms.ToArray();
                                blockTag        = encryptor.GetTag();
                            }

                    // Make sure we got the same results in both cases
                    Assert.IsTrue(Util.CompareBytes(wholeCiphertext, blockCiphertext));
                    Assert.IsTrue(Util.CompareBytes(wholeTag, blockTag));

                    aes.Tag = wholeTag;

                    // Decrypt the whole block of data at once
                    using (ICryptoTransform decryptor = aes.CreateDecryptor())
                    {
                        byte[] wholePlaintext = decryptor.TransformFinalBlock(wholeCiphertext, 0, wholeCiphertext.Length);
                        Assert.IsTrue(Util.CompareBytes(plaintext, wholePlaintext));
                    }

                    // Decrypt the data in chunks
                    using (MemoryStream ms = new MemoryStream())
                        using (ICryptoTransform decryptor = aes.CreateDecryptor())
                            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                            {
                                int chunkSize = 128;
                                for (int offset = 0; offset < blockCiphertext.Length; offset += chunkSize)
                                {
                                    cs.Write(blockCiphertext, offset, chunkSize);
                                }
                                cs.FlushFinalBlock();

                                byte[] blockPlaintext = ms.ToArray();
                                Assert.IsTrue(Util.CompareBytes(plaintext, blockPlaintext));
                            }
                }
            }
        }
예제 #10
0
        /// <summary>
        ///     Perform a round trip test given input and the expected output
        /// </summary>
        private void AuthenticatedAesCngRoundTripTest(RoundTripTestData testData)
        {
            using (AuthenticatedAesCng aes = new AuthenticatedAesCng())
            {
                aes.CngMode = testData.ChainingMode;

                if (testData.Key != null)
                {
                    aes.Key = testData.Key;
                }

                if (testData.IV != null)
                {
                    aes.IV = testData.IV;
                }

                if (testData.AuthenticationData != null)
                {
                    aes.AuthenticatedData = testData.AuthenticationData;
                }

                if (testData.ExpectedTag != null)
                {
                    aes.Tag = testData.ExpectedTag;
                }

                // Encrypt
                byte[] ciphertext = null;
                byte[] tag        = null;
                using (MemoryStream ms = new MemoryStream())
                    using (IAuthenticatedCryptoTransform encryptor = aes.CreateAuthenticatedEncryptor())
                        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(testData.Plaintext, 0, testData.Plaintext.Length);
                            cs.FlushFinalBlock();

                            tag        = encryptor.GetTag();
                            ciphertext = ms.ToArray();

                            // Check if the ciphertext and tag are what are expected.
                            if (testData.ExpectedCiphertext != null)
                            {
                                Assert.IsTrue(Util.CompareBytes(testData.ExpectedCiphertext, ciphertext));
                            }

                            if (testData.ExpectedTag != null)
                            {
                                Assert.IsTrue(Util.CompareBytes(testData.ExpectedTag, tag));
                            }
                        }

                if (testData.ExpectedTag == null)
                {
                    aes.Tag = tag;
                }

                // Decrypt
                using (MemoryStream ms = new MemoryStream())
                    using (ICryptoTransform decryptor = aes.CreateDecryptor())
                        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
                        {
                            cs.Write(ciphertext, 0, ciphertext.Length);
                            cs.FlushFinalBlock();

                            // Compare the decrypted text to the initial ciphertext.
                            byte[] decrypted = ms.ToArray();
                            Assert.IsTrue(Util.CompareBytes(testData.Plaintext, decrypted));
                        }
            }
        }
예제 #11
0
        /// <summary>
        ///     Utility method to help write AES round-trip tests
        /// </summary>
        private static bool RoundTripHelper(byte[] input,
                                            Type encryptionAlgorithm,
                                            Type decryptionAlgorithm,
                                            Action <SymmetricAlgorithm> encryptionSetup)
        {
            // Encryption parameters
            byte[]      key         = null;
            byte[]      iv          = null;
            CipherMode  cipherMode  = CipherMode.CBC;
            PaddingMode paddingMode = PaddingMode.PKCS7;

            // Round tripping data
            byte[] cipherText = null;

            SymmetricAlgorithm encryptionObject = null;

            try
            {
                // Setup the encryption algorithm
                encryptionObject = (SymmetricAlgorithm)Activator.CreateInstance(encryptionAlgorithm);
                encryptionSetup(encryptionObject);

                // Encrypt the data
                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, encryptionObject.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(input, 0, input.Length);
                        cs.FlushFinalBlock();

                        cipherText = ms.ToArray();
                    }

                // Save the encryption parameters
                key         = encryptionObject.Key;
                iv          = encryptionObject.IV;
                cipherMode  = encryptionObject.Mode;
                paddingMode = encryptionObject.Padding;
            }
            finally
            {
                if (encryptionObject != null)
                {
                    (encryptionObject as IDisposable).Dispose();
                }
            }

            byte[] roundTrip = null;

            // Now verify the data
            SymmetricAlgorithm decryptionObject = null;

            try
            {
                decryptionObject = (SymmetricAlgorithm)Activator.CreateInstance(decryptionAlgorithm);

                decryptionObject.Key     = key;
                decryptionObject.IV      = iv;
                decryptionObject.Mode    = cipherMode;
                decryptionObject.Padding = paddingMode;

                using (MemoryStream ms = new MemoryStream())
                    using (CryptoStream cs = new CryptoStream(ms, decryptionObject.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherText, 0, cipherText.Length);
                        cs.FlushFinalBlock();

                        roundTrip = ms.ToArray();
                    }
            }
            finally
            {
                if (decryptionObject != null)
                {
                    (decryptionObject as IDisposable).Dispose();
                }
            }

            return(Util.CompareBytes(input, roundTrip));
        }