使用 OpenSSL 的 AES-256/CBC 加密和 C# 中的解密

时间:2023-03-28
本文介绍了使用 OpenSSL 的 AES-256/CBC 加密和 C# 中的解密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I am a newbie to cryptography. My requirement is to decrypt/encrypt the text that is encrypted/decrypted using openssl. The algorithm that we are using is aes-256-cbc in the Openssl. So, I am trying to implement the same functionality in my application. so far after a lot of googling all i was able to do is..

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 命令是

My openssl command is

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

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

My key length is 32digits and iv is 16digits

谢谢...

推荐答案

首先,阅读openssl的man enc.使用 -k 时会忽略 -iv.您可能想要大写 -K.其次,与 openssl 工具一起使用时,key 和 iv 值是十六进制的,如果您的 C# 使用与命令行相同的字符串,那么您需要执行 适当的转换而不是 Encoding.ASCII.GetBytes(7 位编码无论如何都不是正确的答案).

First, read man enc for openssl. -iv is ignored when -k is used. You probably want capital -K. Second, the key and iv values are hexadecimal when used with the openssl tool, if your C# is using the same string as the command line then you need to do appropriate conversions rather than Encoding.ASCII.GetBytes (a 7 bit encoding is never the right answer anyway).

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

For your plain text, you might as well use Encoding.UTF8.GetBytes/GetString since it is backwards compatible with ASCII.

如果出于某种原因你真的想使用小写的-k,一个生成密钥和iv的密码,这要困难得多,因为openssl使用它自己的密钥派生方案.此外,与 -nosalt 标志一起使用也很危险.

If for some reason you actually want to use lowercase -k, a password to generate both the key and iv, that is much more difficult as openssl uses it's own key derivation scheme. Also, it is dangerous to use with the -nosalt flag.

-nosalt:在密钥派生例程中不使用盐.这个选项应该除非用于测试目的或与古代兼容,否则不得使用OpenSSL 和 SSLeay 的版本.

-nosalt: doesn't use a salt in the key derivation routines. This option SHOULD NOT be used except for test purposes or compatibility with ancient versions of OpenSSL and SSLeay.

这是危险的原因之一,是因为 IV 不应该是可预测的或不能重复用于 AES-CBC,如果您不使用盐,密码将始终生成具有相同 IV 的相同密钥这会使您遭受多次攻击,并可能泄露有关明文的信息.

One of the reasons this is dangerous, is due to the fact that IV's should not be predictable or reused for AES-CBC and if you don't use a salt, the passphrase will always produce the same key with the same IV that opens you up to several attacks and can leak info about the plaintext.

您可以从这篇博文中了解如何从密码短语、与 openssl 相同的密钥和 IV 派生 在 C# 中解密 OpenSSL AES 文件 虽然它是专门针对 AES-128 的,但注释会引导您了解如何修改 aes-256,来自 manEVP_BytesToKey:

You can find out how to derive from passphrase, the same key and IV as openssl from this blog post Decrypting OpenSSL AES files in C# although it is specifically for AES-128 the comments lead you to how to modify for aes-256, from man EVP_BytesToKey:

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# 中的解密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:如何在 C# 中将字符串转换为字节 [] 下一篇:在 C# 中加载 ASN.1/DER 编码的 RSA 密钥对

相关文章