4

I have an AES Cryptography wrapper and unit tests that has been working for over a year. Now after installing VS 2012 (or maybe an update to .net Framework 4) the unit tests do not pass. The streamreader block was throwing a CryptographicException when I passed in a bad pass but is not throwing a ArgumentNullException.

The code is up at. https://github.com/jnaus/Cryptography


Here is the unit test that now does not work. (BadSaltTest has the same problem)

[TestMethod]
[ExpectedException(typeof(CryptographicException),
  "Bad password was inappropriately allowed")]
public void BadPasswordTest()
{
    var cipherText = EncryptString();
    var decryptedText = AESCryptography.DecryptStringAES
        (cipherText,"A bad password", salt);
}

Test Result: Test method CryptographyTest.AESTest.BadPasswordTest threw exception System.ArgumentNullException, but exception System.Security.Cryptography.CryptographicException was expected. Exception message: System.ArgumentNullException: Value cannot be null. Parameter name: inputBuffer

Decrypt code.

public static string DecryptStringAES(string cipherText, 
    string password, byte[] salt)
{   
    RijndaelManaged aesAlg = null;
    string plaintext = null;

    try 
    {
        // generate the key from the shared secret and the salt
        Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt);

        // Create a RijndaelManaged object
        // with the specified key and IV.
        aesAlg = new RijndaelManaged();
        aesAlg.Key = key.GetBytes(aesAlg.KeySize/8);
        aesAlg.IV = key.GetBytes(aesAlg.BlockSize/8);

        // Create a decrytor to perform the stream transform.
        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, 
            aesAlg.IV);
        // Create the streams used for decryption.                
        byte[] bytes = Convert.FromBase64String(cipherText);

        using (MemoryStream msDecrypt = new MemoryStream(bytes)) 
        {
            using (CryptoStream csDecrypt = 
                new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
            {
                //StreamReader now gives ArgumentNullException
                using (StreamReader srDecrypt = new StreamReader(csDecrypt)) 
                {
                    // Read the decrypted bytes from the decrypting stream
                    // and place them in a string.
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    finally 
    {
        // Clear the RijndaelManaged object.
        if (aesAlg != null)
        {
            aesAlg.Clear();
        }
    }
    return plaintext;
}
4

2 回答 2

2

在搜索了更多之后,这确实似乎是 Microsoft 确认的错误(请参阅Microsoft Connect)。个人不是建议的解决方法的忠实粉丝,因为它确实不需要,但我想它会在同一时间做。

于 2012-12-06T12:51:47.780 回答
1

您在上面发布的代码对我有用(我必须编写一些代码来创建要传递的加密字符串)。使用 .Net Framework 4 在 VS2012 中编译和运行。

我使用的加密代码是:

    private static string EncryptStringAES(string plainText, string password, byte[] salt)
    {
        RijndaelManaged aesAlg = null;
        string cypherText = null;

        try
        {
            // generate the key from the shared secret and the salt
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt);

            // Create a RijndaelManaged object
            // with the specified key and IV.
            aesAlg = new RijndaelManaged();
            aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
            aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);

            // Create an encryptor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            // Create the streams used for encryption.                
            byte[] bytes = new UTF8Encoding().GetBytes(plainText);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    csEncrypt.Write(bytes, 0, bytes.Length);
                    csEncrypt.FlushFinalBlock();
                    cypherText = Convert.ToBase64String(msEncrypt.ToArray());
                }
            }
        }
        finally
        {
            // Clear the RijndaelManaged object.
            if (aesAlg != null)
            {
                aesAlg.Clear();
            }
        }
        return cypherText;
    }

使用以下内容进行方法调用:

        byte[] salt =  new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
        string test = DecryptStringAES(EncryptStringAES("This is a test", "Test", salt), "Test", salt);

结果字符串(测试)包含“这是一个测试”。

于 2012-09-21T21:02:08.900 回答