![](/img/trans.png)
[英]C# AES 128 CBC with -nosalt producing different results than openssl AES -128-cbc -nosalt
[英]Decrypting AES in C# where the file was encryped using OpenSSL -nosalt; the AES is expecting a size 16 byte array IV?
提前感謝您的閱讀。
目標是從命令行加密並從 c# 解密,同時盡可能簡單。 我從文檔開始: https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.aes?view=net-5.0
我有一個使用此 OpenSSL 命令(無鹽)加密的文件:
openssl enc -nosalt -aes-128-cbc -in my_file.txt -out my_file.txt.enc -p -pass pass:hello_this_is_pass
並輸出 Key 和 IV
key=2F77B7A1D3BBAA3304E53D791819958A
iv =9DD22E07DD38AF129D42E8CF3689EADD
一旦進入VS,這些被讀入字節arrays:
byte[] key = Encoding.ASCII.GetBytes("2F77B7A1D3BBAA3304E53D791819958A");
byte[] iv = Encoding.ASCII.GetBytes("9DD22E07DD38AF129D42E8CF3689EADD");
var encodedBytes = File.ReadAllBytes("myEncFile.txt.enc");
該文件被讀入一個字節數組:
這從文檔傳遞給閱讀方法:
static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV; // **This is the line that errors**
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
設置aesAlg.IV
會引發以下錯誤:
System.Security.Cryptography.CryptographicException: 'Specified initialization vector (IV) does not match the block size for this algorithm.'
看起來 aesAlg.IV 的默認值為 byte[16]。 我知道這意味着我提供的 IV 是應有的兩倍大,所以我認為我必須使用錯誤的解密器設置
密鑰大小為 byte[32],我嘗試在分配 aesAlg.IV 之前配置實例,但這些更改似乎沒有效果:
aesAlg.Mode = CipherMode.CBC;
aesAlg.IVSize = 128;
aesAlg.BlockSize = 128;
aesAlg.FeedbackSize = 128;
aesAlg.Padding = PaddingMode.None;
我覺得我缺少一些非常明顯的東西。 此處的類似問題涉及加密,或者除非指定 -nosalt,否則 openssl 將自動添加“Salt__”這一事實。 還有一個類似名稱的問題“如何使用 C# 重新加密,以便能夠使用 OpenSSL CLI 工具進行解密?” 但這並不能解決我遇到的錯誤(至少據我所知)。 我覺得我離文檔如此之近,以至於我不能成為唯一會遇到這種情況的人?
如果將來有人發現這一點,@Topaco 在評論中發布了答案。 解決方法是改變
byte[] key = Encoding.ASCII.GetBytes("2F77B7A1D3BBAA3304E53D791819958A");
byte[] iv = Encoding.ASCII.GetBytes("9DD22E07DD38AF129D42E8CF3689EADD");
至
byte[] key = StringToByteArrayFastest("2F77B7A1D3BBAA3304E53D791819958A");
byte[] iv = StringToByteArrayFastest("9DD22E07DD38AF129D42E8CF3689EADD");
使用如何將十六進制字符串轉換為字節數組中的 StringToByteArrayFastest()?
public static byte[] StringToByteArrayFastest(string hex)
{
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.