我正在尝试使用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支持的第三方实用程序解密文件,让我相信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:
知道我做错了吗?
答案 0 :(得分:5)
我找到了使用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;
感谢this answer让我朝着正确的方向前进,并感谢其他人的回答!
答案 1 :(得分:4)
这个enqrypt工具似乎很傻:
DUMMY_DUMMY_DUMM
。对于CBC,如果对多个消息使用相同的密钥,则初始化向量应基本上是随机的,并且任何攻击者都无法预测。
您可以解决固定IV问题:只需在一个块(128位= 16字节)的随机数据前加上您的明文,使用固定的初始化向量进行加密,然后在解密后再次关闭第一个块。由于每个块的密文都像下一个块的初始化向量一样使用,因此应该为实际数据提供足够的随机化。
但是由于enqrypt只是一个简单的演示命令行工具,我认为你应该使用sarnold推荐的openssl
命令行工具,或者使用OpenSSL库函数直接(如果你在那里写一个程序)。
答案 2 :(得分: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
。