问题描述
openssl enc -d -aes-256-cbc -in my_encrypted_file.csv.enc -out my_decrypted_file.csv -pass file:key.bin
其他信息:
我一直在尝试通过搜索网络找到的各种示例。 问题在于,所有这些示例都需要IV(初始化向量)。不幸的是,我没有静脉输液,团队中没有人知道这是什么或如何定义。 openssl命令似乎不需要一个,因此对此我有些困惑。
目前,我正在尝试使用的代码如下:
public static string DecryptAesCbc(byte[] cipheredData,byte[] key)
{
string decrypted;
System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create();
aes.KeySize = 256;
aes.Key = key;
byte[] iv = new byte[aes.BlockSize / 8];
aes.IV = iv;
aes.Mode = CipherMode.CBC;
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key,aes.IV);
using (MemoryStream ms = new MemoryStream(cipheredData))
{
using (CryptoStream cs = new CryptoStream(ms,decipher,CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decrypted = sr.ReadToEnd();
}
}
return decrypted;
}
}
代码无法说明我的byte [256]键的长度对于这种算法而言是错误的。
谢谢您的帮助!
干杯,迈克
解决方法
发布的OpenSSL语句使用-pass file:
选项,因此使用了口令(从文件中读取),请参见openssl enc。这导致加密过程首先生成随机 8字节盐,然后与密码短语一起使用(不是很安全)专有的OpenSSL函数{{1来导出32字节密钥和16字节IV。 }}。此功能使用多个参数,例如摘要和迭代计数。密钥派生的默认摘要为 MD5 ,迭代次数为1。请注意,OpenSSL版本1.1.0和更高版本将 SHA256 用作默认摘要,即,取决于用于生成密文的OpenSSL版本,必须使用适当的摘要进行解密。在密文之前是一个块,其前8个字节是EVP_BytesToKey
的ASCII编码,后跟8个字节的salt。
因此,解密必须首先确定盐。必须根据盐和密码短语一起导出密钥和IV,然后才能解密其余的加密数据。因此,首先需要在C#中实现Salted__
,例如here。然后可能的实现方式是(使用 MD5 作为摘要):
EVP_BytesToKey
请注意,public static string DecryptAesCbc(byte[] cipheredData,string passphrase)
{
string decrypted = null;
using (MemoryStream ms = new MemoryStream(cipheredData))
{
// Get salt
byte[] salt = new byte[8];
ms.Seek(8,SeekOrigin.Begin);
ms.Read(salt,8);
// Derive key and IV
OpenSslCompat.OpenSslCompatDeriveBytes db = new OpenSslCompat.OpenSslCompatDeriveBytes(passphrase,salt,"MD5",1);
byte[] key = db.GetBytes(32);
byte[] iv = db.GetBytes(16);
using (Aes aes = Aes.Create())
{
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
// Decrypt
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key,aes.IV);
using (CryptoStream cs = new CryptoStream(ms,decipher,CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs,Encoding.UTF8))
{
decrypted = sr.ReadToEnd();
}
}
}
}
return decrypted;
}
的第二个参数是密码短语(如DecryptAesCbc
)而不是密钥(如string
)。另请注意,StreamReader
使用一种编码(默认为UTF-8),该编码需要兼容的数据(即文本数据,但是csv文件应满足此要求)。否则(例如,对于二进制数据而不是文本数据)不得使用byte[]
。