C# 无法解密使用AES加密的文件

C# 无法解密使用AES加密的文件,c#,.net,encryption,cryptography,aes,C#,.net,Encryption,Cryptography,Aes,我正试图使用System.Security.Cryptography.aessmanaged对.net应用程序中的文件进行加密。它需要在嵌入式Linux环境中解密,因此.net库对我不可用 我目前拥有的代码如下所示: string encPassword = "ABCDABCDABCDABCDABCDABCDABCDABCD"; string sourceFile = "myFile.txt"; string targetFile = "myFile.encrypted.txt"; FileSt

我正试图使用
System.Security.Cryptography.aessmanaged
对.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;
}
// ...
enqrypt.exe -d -aes -256 -cbc -k ABCDABCDABCDABCDABCDABCDABCDABCD myFile.encrypted.txt
其中
-d
表示解密,
-256
表示密钥大小,
-cbc
表示模式,
-k
位于密钥之前

它没有给我原始文件

我已经尝试了一些第三方实用程序,但我似乎无法解密它

我尝试加密和解密此文件时是否存在任何明显错误

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

代码中的块大小仍然是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:

知道我做错了什么吗?

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;
/* ... */
//伪数据,可用作iv/键
无符号字符*gDummy=(无符号字符*)“DUMMY\u DUMMY\u DUMMY\u DUMMY\u DUMMY\u DUMMY”;
/* ... */
if(algou_AES==gAlgorithm){
无符号字符*iv=(无符号字符*)malloc(AES_块大小);
memcpy(iv、gDummy、AES_块大小);
int rc,num=0;

如果(!gMem)和&(gMode这个enqrypt工具看起来很傻:

  • 它只允许直接输入密钥,不允许使用base64或十六进制编码,这就不允许使用任何非base64或十六进制编码的密钥 在所使用的编码中可表示(或不容易作为命令行参数键入)
  • 它使用一个固定的初始化向量
    DUMMY\u DUMM
对于CBC,如果对多条消息使用同一密钥,则初始化向量本质上应该是随机的,任何攻击者都无法预测

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


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

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

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

但最后一个问题是,我在设置键后设置键大小:

如果我将上述代码更改为以下代码,我可以使用
openssl
对其进行解密:

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

多亏了这一点,我走上了正确的方向,也多亏了其他人的回答!

enqrypt的用法如下:
enqrypt.exe[-e |-d |-b][aes |-des |-3des |-blowfish |-rc4][196 256][ecb |-cbc |-cfb |-ofb][k key |数据mem文件名
。似乎没有任何方法可以传递
IV
,除非我弄错了?基于这个原理,如果我将编码端的IV硬编码为
DUMMY\u DUMM
,它应该解码,对吗?当我将代码中的
IV
初始化更改为
byte[]IV=Encoding.ASCII.GetBytes时(“哑巴”
很遗憾,这可能没有什么不同。我是否正确地将密钥传递给
enqrypt
?在我的代码中,密钥是从纯文本字符串的ASCII值生成的。在解密端,我将原始纯文本字符串作为密钥传递。对吗?我认为
enqrypt
直接使用您的ASCII值作为密钥键,但这是一些相当尴尬的代码。由于这东西只是调用OpenSSL,您可以使用非常好的
OpenSSL(1)
命令行工具吗?太棒了!很抱歉,我错过了密钥大小问题--这听起来像是一个可怕的问题。做得好。:)谢谢-我也尝试过使用
openssl
,但在尝试解密时出现了一个错误“坏的魔法数字”。这是我的命令行用法:
openssl enc-d-aes-256-cbc-in“c:\Encrypted.txt”-out“c:\Decrypted.txt”“-pass pass:ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDCDABCDABCDCDABCDABCDABCDCDABCDCDABCDABCDCDABCDABCDABCDABCDABCDABCDCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDCDABCDABCDCDABCDCDABCDABCDCDCDABCDABCDABCDABCDABCDABCDCDCDABCDABCDCDABCDABCDABCDCDCDCDCDCDABCDABCDABCDCD因此,看看我上面的代码,我的
IV
只是密钥的前16个字节,对吗?是的。这本身是个坏主意,但你可以尝试一下,看看它是否在这里工作。谢谢你的帮助-我已经用最新状态更新了问题。你能看看,让我知道我可能做错了什么吗?你最后的错误消息看起来OpenSSL需要一些填充方案,但不存在(但这也可能是由于密钥/IV组合错误造成的)。此外,您只传递16字节的密钥,而AES-256需要32字节的密钥。(我不知道当您传递太多密钥时OpenSSL和.NET在做什么。)
AesManaged aes = new AesManaged();
aes.Key = key;
aes.IV = IV;
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
AesManaged aes = new AesManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = key;
aes.IV = IV;
aes.Mode = CipherMode.CBC;