[英]Implement PHP method openssl_encrypt "AES-256-CBC" OPENSSL_RAW_DATA in C#
[英]Decrypt AES-256-CBC with PBKDF2 from OpenSSL in C#
我需要解密一個用 OpenSSL 加密的字符串,如下所示:
openssl rand -out secret.key -hex 192
openssl aes-256-cbc -pbkdf2 -in file_to_encrypt -out encrypted_file -pass file:secret.key
我不能讓它在 C# 中工作
public void OnStartup()
{
using var rsa = RSA.Create();
var privateKeyContent = File.ReadAllText("/cert/customer.pem");
rsa.ImportFromPem(privateKeyContent);
var encryptedSecret = File.ReadAllBytes("license/secret.key.enc");
var decrypted = rsa.Decrypt(encryptedSecret, RSAEncryptionPadding.Pkcs1);
_logger.LogInformation(Encoding.UTF8.GetString(decrypted));
var bytes = File.ReadAllBytes("license/license.json.enc");
var license = DecryptAesCbc(bytes, decrypted);
_logger.LogInformation(license);
}
public string DecryptAesCbc(byte[] cipheredData, byte[] passphrase)
{
string decrypted = null;
using (var ms = new MemoryStream(cipheredData))
{
// Get salt
var salt = new byte[8];
ms.Seek(8, SeekOrigin.Begin);
ms.Read(salt, 0, 8);
_logger.LogInformation("Salt: {Salt}", string.Concat(Array.ConvertAll(salt, x => x.ToString("X2"))));
// Derive key and IV
var pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, 10000, HashAlgorithmName.SHA256);
byte[] key = pbkdf2.GetBytes(32);
byte[] iv = pbkdf2.GetBytes(16);
_logger.LogInformation("Key: {Key}", string.Concat(Array.ConvertAll(key, x => x.ToString("X2"))));
_logger.LogInformation("IV: {IV}", string.Concat(Array.ConvertAll(iv, x => x.ToString("X2"))));
using Aes aes = Aes.Create();
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
// Decrypt
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using var cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read);
using var sr = new StreamReader(cs, Encoding.UTF8);
decrypted = sr.ReadToEnd();
}
return decrypted;
}
使用此代碼,我在decrypted = sr.ReadToEnd()
處收到異常Padding is invalid and cannot be removed.
秘密通過RSA加密並解密,結果與解密文件相同,所以這應該可以工作。
我非常感謝您的幫助
解決方案:
public static string DecryptLicense(byte[] cipherData, byte[] passphrase)
{
string decrypted = null;
using (var ms = new MemoryStream(cipherData))
{
// Get salt
var salt = new byte[8];
ms.Seek(8, SeekOrigin.Begin);
ms.Read(salt, 0, 8);
// Derive key and IV
var pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, 10000, HashAlgorithmName.SHA256);
byte[] key = pbkdf2.GetBytes(32);
byte[] iv = pbkdf2.GetBytes(16);
using Aes aes = Aes.Create();
aes.KeySize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
// Decrypt
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using var cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read);
using var sr = new StreamReader(cs, Encoding.UTF8);
decrypted = sr.ReadToEnd();
}
return decrypted;
}
並使用以下命令生成密碼: openssl rand 192 | openssl enc -A -base64 -out secret.key
openssl rand 192 | openssl enc -A -base64 -out secret.key
問題是一個用換行符生成的密碼,openssl 只使用密碼文件的第一行,但 C# 使用整個文件來派生密鑰。 為了防止這種情況,我現在生成一個沒有換行符的文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.