ASP.net rijndael decrypt - 要解密的数据长度

时间:2009-11-04 16:06:08

标签: asp.net encryption rijndaelmanaged rijndael

到目前为止,我发现的很多项目都有点模糊或......非特定,所以我希望得到答案。

我有两个小方法 - 容易看起来像......

    private const string initVector = "1234567890123456";
    private const string SaltValue = "ThisIsMySaltValue";
    private const int KeySize = 256;

    public static string Encrypt(string textToEncrypt)
    {
        var rijndael = new RijndaelManaged {KeySize = KeySize};
        var salt = SaltValue.ToByteArray();
        var vector = initVector.ToByteArray();

        var rfcBytes = new Rfc2898DeriveBytes(vector, salt, 2);
        var key = rfcBytes.GetBytes(rijndael.KeySize/8);

        ICryptoTransform encrypt = rijndael.CreateEncryptor(key, vector);

        var stream = new MemoryStream();
        var data = Encoding.ASCII.GetBytes(textToEncrypt);
        stream.Write(data, 0, data.Length);

        var cryptoStream = new CryptoStream(stream, encrypt, CryptoStreamMode.Write);
        cryptoStream.Write(data, 0, data.Length);
        cryptoStream.FlushFinalBlock();

        cryptoStream.Close();
        return Convert.ToBase64String(stream.ToArray());
    }


    public static string Decrypt(string textToDecrypt)
    {
        var vector = initVector.ToByteArray();
        var salt = SaltValue.ToByteArray();
        var encrypted = textToDecrypt.ToByteArray();

        var rijndael = new RijndaelManaged {KeySize = KeySize};

        var rfcBytes = new Rfc2898DeriveBytes(vector, salt, 2);
        var key = rfcBytes.GetBytes(rijndael.KeySize/8);

        var decrypt = rijndael.CreateDecryptor(key, vector);

        var stream = new MemoryStream(encrypted);
        var cryptoStream = new CryptoStream(stream, decrypt, CryptoStreamMode.Read);

        byte[] plainBytes = new byte[textToDecrypt.Length];

        var decryptedLength = cryptoStream.Read(plainBytes, 0, plainBytes.Length);

        var plainText = Encoding.UTF8.GetString(plainBytes, 0, decryptedLength);
        return plainText;
    }

单元测试看起来像这样......

    [Test]
    public void JustTestingThisOut()
    {
        var encryptMe = "SomethingToEncrypt";
        string result = encryptMe.ConvertToEncrypted();
        result.ShouldNotEqual(encryptMe);
        string backToReadAble = result.ConvertToDecrpted();
        backToReadAble.ShouldEqual(encryptMe);
    }

ToByteArray只返回Encoding.UTF8.GetBytes(toByte);我的测试字符串很简单 - “SomethingToEncrypt”。我找到this认为可能是问题(Convert.ToBase64String和Convert.FromBase64String)似乎没有任何区别的兔子洞。至于错误...

  

测试用例   'Tests.Encryption.EncryptionUnitTests.JustTestingThisOut'   失败:   System.Security.Cryptography.CryptographicException   :要解密的数据的长度是   无效。在   System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(字节[]   inputBuffer,Int32 inputOffset,Int32   inputCount)

我有FlushFinalBlock(),我认为这样做,但是......不,也没有区别。有任何想法吗?要尝试的事情?

3 个答案:

答案 0 :(得分:0)

加密时,首先将data写入stream,然后用stream包裹CryptoStream并再次写data,这次加密。为什么?解密失败是因为遇到的第一件事是未加密的数据。

在 base64编码之前打印密文的值以验证这一点。你应该看到明文后面跟着一堆gobbledygook作为密文。

此外,您使用初始化向量作为密码。它们绝对不是一回事,像这样使用会损害安全性。

答案 1 :(得分:0)

我无法看到这将如何起作用,因为在你执行的解密功能中

var encrypted = textToDecrypt.ToByteArray();

这里textToDecrypt是一个base64字符串。首先必须将base64转换回普通字节,然后可以使用它来解密。

答案 2 :(得分:0)

您的代码中潜伏着间歇性的错误......

您绝不应将任何System.Text.Encoding类用于密文。您遇到间歇性错误。您应该使用Base64编码和System.Convert类方法。

  1. 要从加密字节[]获取加密字符串,您应该使用:
  2. Convert.ToBase64String(byte[] bytes)

    1. 要从要加密的字符串中获取原始字节[],您应该使用:
    2. Convert.FromBase64String(string data)

      另外需要注意的是,在进行加密时您需要FlushFinalBlock(),否则无法正确填充。

      有关其他信息,请参阅MS安全大师Shawn Fanning的帖子http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx