簡體   English   中英

無法解密使用AesManaged加密的文件

[英]Unable to decrypt file encrypted using AesManaged

我試圖使用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;
}
// ...

這可以加密文件。 現在我試圖在Linux上使用Linux支持的第三方實用程序解密文件,讓我相信Linux開發人員能夠解密它。

快速搜索SourceForge讓我進入Enqrypt 但是,如果我在加密文件上使用Enqrypt ,如下所示:

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

其中-d表示解密, -256表示密鑰大小, -cbc表示密鑰, -k表示密鑰。

它沒有給我原始文件。

我嘗試了一些第三方實用程序,但我似乎無法解密它。

我試圖加密和解密這個文件有什么明顯的錯誤嗎?

更新

根據@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解密我的問題的解決方案(在問題的更新部分)。

首先,我的密鑰長度是錯誤的(正如@PaŭloEbermann所建議的那樣) - 應該是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;

感謝這個回答讓我朝着正確的方向前進,並感謝其他人的回答!

這個enqrypt工具似乎很傻:

  • 它只允許直接輸入密鑰,不允許使用base64或十六進制編碼,這樣就不允許在使用的編碼中使用任何不可表示(或不容易作為命令行參數輸入)的鍵。
  • 它使用DUMMY_DUMMY_DUMM的固定初始化向量。

對於CBC,如果對多個消息使用相同的密鑰,則初始化向量應該基本上是隨機的,並且任何攻擊者都無法預測。

您可以解決固定IV問題:只需在一個塊(128位= 16字節)的隨機數據前加上您的明文,使用固定的初始化向量進行加密,然后在解密后再次關閉第一個塊。 由於每個塊的密文都像下一個塊的初始化向量一樣使用,因此應該為實際數據提供足夠的隨機化。

但由於enqrypt只是一個簡單的示范命令行工具 ,我認為您應該使用sarnold推薦的openssl命令行工具,或直接使用OpenSSL庫函數(如果您在那里編寫程序)。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM