使用C#进行AES 256位解密,给定加密文本和密钥。

3

有人问我,如果我知道一个AES 256位加密的字符串的秘钥,我该如何解密它。由于我对加密不太熟悉,所以我开始探究这个问题。

我在MSDN上找到了这个示例,并尝试修改它只进行解密:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

internal class AesExample
{
    public static void Main()
    {
        var encryptedString = "U2FsdGVkX1/cHT8XuHCfpw0AV4jpaO8JfLqUeCRJqjY=";
        var secret = "SPARKY";

        // I know this is not the correct way to get my input byte arrays...
        // Just illustrating that I DO need byte arrays.
        var encryptedBytes = Encoding.UTF8.GetBytes(encryptedString);
        var secretBytes = Encoding.UTF8.GetBytes(secret);

        try
        {
            using (var aes = new AesManaged())
            {
                aes.Key = secretBytes;

                // Decrypt the bytes to a string. 
                var decryptedString = Decrypt(encryptedBytes, aes.Key, aes.IV);

                //Display the original data and the decrypted data.
                Console.WriteLine("Encrypted: {0}", encryptedString);
                Console.WriteLine("Decrypted: {0}", decryptedString);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: {0}", e.Message);
        }
    }

    private static string Decrypt(byte[] cipherText, byte[] key, byte[] iv)
    {
        // Declare the string used to hold 
        // the decrypted text. 
        string plaintext;

        // Create an AesManaged object 
        // with the specified key and IV. 
        using (var aes = new AesManaged())
        {
            aes.Key = key;
            aes.IV = iv;

            // Create a decrytor to perform the stream transform.
            var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

            // Create the streams used for decryption. 
            using (var msDecrypt = new MemoryStream(cipherText))
            {
                using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (var srDecrypt = new StreamReader(csDecrypt))
                    {
                        // Read the decrypted bytes from the decrypting stream 
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }

        return plaintext;
    }
}

当我运行到以下这一行时,抛出了CryptographicException异常,异常信息为“指定的密钥对于此算法无效。” ==> aes.Key = secretBytes
有人建议对密钥进行SHA1哈希,并将其裁剪为20个字节。 我尝试了一下,结果开始收到新的CryptographicException异常,异常信息为“要解密的数据长度无效。”
所以,我有几个问题:
1)仅给定加密文本和密钥,这是否可能?
2)如果可以,是否需要做出一些基本假设,比如CipherMode?我读到ECB模式没有初始化向量,这就是我问的原因。
3)我需要做些什么才能将输入(加密文本和密钥)转换为正确的Byte []格式以使解密正常工作?
谢谢!

加密字符串不是UTF-16吗?那为什么要编码成UTF-8呢? - Na Na
@NaNa - 我不确定编码是什么,但将其更改为UTF16(.Net中的Encoding.Unicode)会导致相同的“Length of the data to decrypt is invalid”加密异常。 - bopapa_1979
问你这个问题的人,他们有没有说明加密字符串是如何获得的?比如,是使用另一个带有AesManaged或类似功能的C#程序吗?我之所以问这个问题,是因为我曾经尝试将JavaScript代码移植到C#时遇到了问题。JavaScript代码使用的AES实现无法用C#中任何标准的AES类复制。 - Ichabod Clay
@IchabodClay - 不,他们没有。 - bopapa_1979
1
感觉有点像 PHP 代码。PHP 会使用零值字节将密钥扩展到 128 位(然后是 192 位或 256 位,具体取决于大小)。它在填充方面也使用了相同的思路。当然,在加密标准方面,这两者都是完全愚蠢的,但事实就是如此。哦,还有许多 PHP 网站也使用块大小为 256 位的 Rijndael 而不是 AES。 - Maarten Bodewes
2个回答

10

您可能需要更多信息才能使这个工作。回答您的具体问题:

  1. 是的,除了您没有密钥。正如DavidH所提到的,"SPARKY"不是有效的AES密钥,尽管密码通常通过称为 密钥派生函数导出密钥。您可以尝试运行您的密码通过Rfc2898DeriveBytes(.NET中流行的KDF)来派生可能有效的不同AES密钥,但它也需要您显然没有的参数。您还可以尝试使用不同的SHA哈希摘要来处理密码,尽管20字节不是有效的AES密钥-您需要16、24或32字节密钥。
  2. 如果您没有IV,则必须假设加密使用ECB。(但请注意,通常情况下,您不应该使用ECB模式。)
  3. 您的加密字符串似乎使用base64编码。在.NET中,使用Convert.FromBase64String(encryptedString);可以将其转换为字节数组。

这听起来像是一项有趣的练习,但如果没有更多信息,您可能最终会感到沮丧。


2

AES密钥长度为128、192和256位,具体取决于您想使用的密码。您必须确保您的字符串字节长度是适当的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接