使用OpenSSL进行AES-256 / CBC加密并使用C#进行解密

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用OpenSSL进行AES-256 / CBC加密并使用C#进行解密相关的知识,希望对你有一定的参考价值。

我是密码学的新手。我的要求是使用openssl解密/加密加密/解密的文本。我们使用的算法是Openssl中的aes-256-cbc。所以,我试图在我的应用程序中实现相同的功能。到目前为止,经过大量的谷歌搜索,我所能做的就是......

private static string Encryptor(string TextToEncrypt)
{
    //Turn the plaintext into a byte array.
    byte[] PlainTextBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToEncrypt);            

    //Setup the AES providor for our purposes.
    AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();

    aesProvider.BlockSize = 128;
    aesProvider.KeySize = 256;  
    //My key and iv that i have used in openssl
    aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
    aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);  
    aesProvider.Padding = PaddingMode.PKCS7;
    aesProvider.Mode = CipherMode.CBC;

    ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV);            
    byte[] EncryptedBytes = cryptoTransform.TransformFinalBlock(PlainTextBytes, 0, PlainTextBytes.Length);
    return Convert.ToBase64String(EncryptedBytes);                        
}

private static string Decryptor(string TextToDecrypt)
{
    byte[] EncryptedBytes = Convert.FromBase64String(TextToDecrypt);

    //Setup the AES provider for decrypting.            
    AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
    //aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
    //aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
    aesProvider.BlockSize = 128;
    aesProvider.KeySize = 256;  
    //My key and iv that i have used in openssl
    aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
    aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);  
    aesProvider.Padding = PaddingMode.PKCS7;
    aesProvider.Mode = CipherMode.CBC;


    ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
    byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
    return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
}

我的openssl命令是

openssl aes-256-cbc -e -nosalt -a -in  inputfile.txt -out  output.txt -k key -iv ivkey

我的密钥长度为32位,iv为16位

Thnx ......

答案

首先,阅读man enc for openssl。当使用-iv时,忽略-k。你可能想要资本-K。其次,当使用openssl工具时,key和iv值是十六进制的,如果你的C#使用与命令行相同的字符串,那么你需要做appropriate conversions而不是Encoding.ASCII.GetBytes(无论如何,7位编码永远不是正确的答案)。

对于纯文本,您可以使用Encoding.UTF8.GetBytes/GetString,因为它向后兼容ASCII。

如果由于某种原因你实际上想要使用小写的-k,密码来生成密钥和iv,那就更难了,因为openssl使用它自己的密钥派生方案。此外,使用-nosalt标志是危险的。

-nosalt:在密钥派生例程中不使用salt。除了测试目的或与古老版本的OpenSSL和SSLeay的兼容性之外,不应该使用此选项。

这是危险的原因之一是由于IV不应该是可预测的或重复用于AES-CBC,如果你不使用盐,密码将始终产生相同的密钥与相同的IV打开你多达几次攻击,可以泄露有关明文的信息。

您可以从这篇博客文章Decrypting OpenSSL AES files in C#中找到如何从密码短语,与openssl相同的密钥和IV导出,尽管它专门针对AES-128,评论将引导您如何修改来自man EVP_BytesToKey的aes-256:

Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)

Key = Hash1 + Hash2
IV = Hash3

以上是关于使用OpenSSL进行AES-256 / CBC加密并使用C#进行解密的主要内容,如果未能解决你的问题,请参考以下文章

AES (aes-cbc-128, aes-cbc-192, aes-cbc-256) 使用 openssl C 加密/解密

错误的加密(QT c++ OpenSSL AES 256 CBC)

OpenSSL -aes-256-cbc解密行为在1.0.2o和1.1.0g之间变化

无法使用来自 AES-256-CBC 的 pgcrypto 解密,但 AES-128-CBC 可以

QT:AES-256-CBC 根据 PHP 代码在 C++ 中加密/解密

Java 等效于 OpenSSL AES CBC 加密