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)); } } }
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)); }
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)); }
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)); }
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)); } } } }
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)); } }
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)); } } } }
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)); } } } }
/// <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)); } } }
/// <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)); }