【问题标题】:Unable to decrypt file encrypted using AesManaged无法解密使用 AesManaged 加密的文件
【发布时间】:2011-11-11 05:34:32
【问题描述】:

我正在尝试使用System.Security.Cryptography.AesManaged 来加密我的 .net 应用程序中的文件。它需要在嵌入式 Linux 环境中解密,因此我无法使用 .net 库。

我现在的代码看起来像这样:

string encPassword = "ABCDABCDABCDABCDABCDABCDABCDABCD";
string sourceFile = "myFile.txt";
string targetFile = "myFile.encrypted.txt";
FileStream fsInput = = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
FileStream fsOutput = new FileStream(targetFile, FileMode.OpenOrCreate, FileAccess.Write);

CryptoStream cryptoStream = null;

try
{
    byte[] key = Encoding.ASCII.GetBytes(encPasswd);
    byte[] IV = new byte[16];
    Array.Copy(key, 0, IV, 0, 16);

    AesManaged aes = new AesManaged();
    aes.Key = key;
    aes.IV = IV;
    aes.BlockSize = 128;
    aes.KeySize = 256;
    aes.Mode = CipherMode.CBC;

    ICryptoTransform encryptor = aes.CreateEncryptor();

    cryptoStream = new CryptoStream(fsOutput, encryptor, CryptoStreamMode.Write);

    byte[] buffer = new byte[BUFFER_LENGTH];
    long bytesProcessed = 0;
    long fileLength = fsInput.Length;
    int bytesInCurrentBlock;

    do
    {
        bytesInCurrentBlock = fsInput.Read(buffer, 0, BUFFER_LENGTH);
        cryptoStream.Write(buffer, 0, bytesInCurrentBlock);
        bytesProcessed = bytesProcessed + bytesInCurrentBlock;
    }
    while (bytesProcessed < fileLength);

    return true;
}
// ...

这可以加密文件。现在我正在尝试在 Windows 上使用 Linux 也支持的第 3 方实用程序来解密该文件,以使我相信 Linux 开发人员能够解密它。

在 SourceForge 上快速搜索让我到 Enqrypt。但是,如果我像这样在加密文件上使用Enqrypt

enqrypt.exe -d -aes -256 -cbc -k ABCDABCDABCDABCDABCDABCDABCDABCD myFile.encrypted.txt

其中-d 表示解密,-256 表示密钥大小,-cbc 表示模式,-k 在密钥前面。

它没有给我原始文件。

我已经尝试过使用一些 3rd 方实用程序,但我似乎无法解密它。

我尝试加密和解密此文件的方式是否存在明显错误?

更新

响应@Paŭlo 的建议,我现在有以下测试代码(别担心,我打算将密钥和IV 更改为不同):

byte[] key = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
byte[] IV =  { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };

代码中块大小仍然是128,密钥大小仍然是256。

我现在尝试使用openssl 解密文件,如下所示:

openssl enc -d -aes-256-cbc -in c:\encrypted.txt -out c:\decrypted.txt -K 11223344556677881122334455667788 -iv 11223344556677881122334455667788

这会导致以下错误:

bad decrypt 11452:error:06065064:digital envelope routines:EVP_DecryptFinal:bad decrypt:evp_enc.c:450:

知道我做错了什么吗?

【问题讨论】:

  • 您的最后一条错误消息看起来像 OpenSSL 需要一些填充方案,但它不存在(但这也可能是由错误的键/IV 组合引起的)。此外,您只传递一个 16 字节的密钥,而 AES-256 需要一个 32 字节的密钥。 (当您传递太短的密钥时,我不知道 OpenSSL 和 .NET 在做什么,但我可以想象它们不会做同样的事情。)
  • @Paŭlo - 我将 key 更改为 32 字节数组,但没有任何区别。填充方案适用于什么,keyIV 或两者都适用? IV的长度应该和key一样吗?
  • CBC 的 IV 长度应与块大小(AES 为 128 位/16 字节)相同,与密钥大小无关。在加密之前将填充方案应用于纯文本,以确保纯文本的大小是块大小的倍数。虽然documentation 表示默认值为 PKCS7,这与 openssl 工具使用的相同。我在这里没有想法......
  • @Paŭlo - 感谢您的所有帮助。我终于找到了解决方案 - 请参阅my answer

标签: c# .net encryption cryptography aes


【解决方案1】:

我找到了使用openssl 解密问题的解决方案(在问题的更新部分)。

首先,我的密钥长度错误(正如@Paŭlo Ebermann 所建议的那样) - 它应该是 256 位。

但最后一个问题是我在 之后设置了密钥大小:

AesManaged aes = new AesManaged();
aes.Key = key;
aes.IV = IV;
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;

如果我把上面的代码改成下面这样,我可以用openssl解密它:

AesManaged aes = new AesManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = key;
aes.IV = IV;
aes.Mode = CipherMode.CBC;

感谢this answer 引导我朝着正确的方向前进,也感谢其他所有人的回答!

【讨论】:

    【解决方案2】:

    这个enqrypt工具好像挺傻的:

    • 它只允许直接输入密钥,不允许使用 base64 或十六进制编码,不允许任何非 在使用的编码中可表示(或不易作为命令行参数键入)。
    • 它使用固定的初始化向量DUMMY_DUMMY_DUMM

    对于 CBC,如果您对多条消息使用相同的密钥,初始化向量应该基本上是随机的,并且任何攻击者都无法预测。

    您可以解决固定 IV 的问题:只需在明文前面添加一个随机数据块(128 位 = 16 字节),使用固定初始化向量进行加密,并在解密后再次剥离第一个块。由于每个块的密文都被用作下一个块的初始化向量,这应该为真实数据提供足够的随机化。

    但由于 enqrypt 只是 一个简单的演示命令行工具,我认为您应该改用 sarnold 推荐的 openssl 命令行工具,或者直接使用 OpenSSL 库函数(如果您正在那里编写程序)。

    【讨论】:

    • 谢谢 - 我也尝试使用openssl,但在尝试解密时收到错误“bad magic number”。这是我的命令行用法:openssl enc -d -aes-256-cbc -in "c:\Encrypted.txt" -out "c:\Decrypted.txt" -pass pass:ABCDABCDABCDABCDABCDABCDABCDABCD。有什么建议么? 31E15C9364939 坏幻数
    • 使用-K 而不是-pass,因为您直接使用密钥。我认为您还需要指定初始化向量,如果它不包含在文件中。 (而且你不应该重复使用你的密钥作为初始化向量!)
    • 那么看看我上面的代码,我的IV 只是密钥的前16个字节,对吧?
    • 是的。这本身就是一个坏主意,但你可以试试看它是否在这里工作。
    • 感谢您的帮助 - 我已将问题更新为最新状态。你能看一下,让我知道我可能做错了什么吗?
    【解决方案3】:

    enqrypt 可能应该因为未初始化 IV 而引发某种错误——加密时您可能使用了所有零字节的IV(假设 C# 为您将内存初始化为零),所以您解密时也应该尝试使用所有零字节。 (请务必将 IV 设置为 真正 使用。)

    更新

    感谢您提供确切的使用说明——这让我很好奇看看enqrypt 源代码,它有解决方案:

    // dummy data, can be used as iv/key
    unsigned char *gDummy = (unsigned char*)"DUMMY_DUMMY_DUMMY_DUMMY_DUMMY_DUMMY_DUMMY";
    /* ... */
        if (ALGO_AES == gAlgorithm) {
            unsigned char *iv = (unsigned char*)malloc(AES_BLOCK_SIZE);
            memcpy(iv, gDummy, AES_BLOCK_SIZE);
            int rc, num=0;
    
            if ((!gMem) && (gMode <= MODE_CBC)) {
                // insert padding info for ECB/CBC modes
                tblk[0] = gSize % AES_BLOCK_SIZE;
                fwrite(tblk, 1, 1, ftar);
            }
    
            while (0 != (rc = fread(sblk, 1, AES_BLOCK_SIZE, fsrc))) {
                switch (gMode) {
                default:
                case MODE_ECB:                           // AES ECB encrypt
                    AES_ecb_encrypt(sblk, tblk, &gEncAesKey, AES_ENCRYPT);
                    if (!gMem) fwrite(tblk, 1, AES_BLOCK_SIZE, ftar);
                    break;
                case MODE_CBC:                            // AES CBC encrypt
                    AES_cbc_encrypt(sblk, tblk, AES_BLOCK_SIZE, &gEncAesKey, iv, AES_ENCRYPT);
                    if (!gMem) fwrite(tblk, 1, AES_BLOCK_SIZE, ftar);
                    break;
    /* ... */
    

    您永远没有机会,因为enqrypt 的作者已将 IV(不是一个好主意)硬编码为 DUMMY_DUMMY_DUMM

    【讨论】:

    • enqrypt的用法如下:enqrypt.exe [-e|-d|-b] [-aes|-des|-3des|-blowfish|-rc4] [-196|-256] [-ecb|-cbc|-cfb|-ofb] [-k key_data] [-mem] filename。似乎没有任何方法可以通过IV,除非我弄错了?
    • 基于这个理由,如果我将编码端的 IV 硬编码为 DUMMY_DUMMY_DUMM 它应该解码,对吧?当我将代码中的IV 初始化更改为byte[] IV = Encoding.ASCII.GetBytes("DUMMY_DUMMY_DUMM"); 时,不幸的是可能没有区别。
    • 我是否将密钥正确传递给enqrypt?在我的代码中,密钥是从纯文本字符串的 ASCII 值生成的。在解密方面,我将原始纯文本字符串作为密钥传递。对吗?
    • 认为 enQrypt 直接使用您的 ASCII 值作为键,但这是一些非常尴尬的代码。既然这个东西只是调用 OpenSSL,你能用更好的openssl(1) 命令行工具代替吗?
    • 太棒了!很抱歉我错过了 keysize 问题——这听起来像是一个可怕的问题。干得好。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    相关资源
    最近更新 更多