【发布时间】:2019-01-06 02:05:41
【问题描述】:
我有以下 PHP 解密例程,它运行完美,需要帮助将其转换为 c#。我尝试了很多方法,但没有一个有效。 我已经设法匹配 c# 和 php 之间的哈希函数输出。 还匹配从和到 base64 的转换输出。
PHP 代码:
function decrypt($encrypted_txt, $secret_key, $secret_iv)
{
$encrypt_method = "AES-256-CBC";
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
$output = openssl_decrypt(base64_decode($encrypted_txt), $encrypt_method, $key, 0, $iv);
return $output;
}
secret_key= "t-3zafRa"; secret_key_hash = "d03a4d94b29e7f55c80726f1152dcebc9f03f4c698470f72083af967cf786b6b";问题是密钥哈希是 64 字节,这对 AES-256 无效,但我不确定它在 php 中的工作方式以及 openssl_decrypt php 函数如何处理密钥。
我也尝试过传递密钥哈希的 MD5 但也未能解密。
byte[] asciiBytes = ASCIIEncoding.ASCII.GetBytes(keyhash);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string keymd5 = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower(); //To match with PHP MD5 output
C# 哈希函数:
static string sha256(string randomString)
{
var crypt = new System.Security.Cryptography.SHA256Managed();
var hash = new System.Text.StringBuilder();
byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}
C#解密例程:
static string DecryptStringFromBytesAes(byte[] cipherText, byte[] key, byte[] iv)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("key");
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException("iv");
// Declare the RijndaelManaged object
// used to decrypt the data.
RijndaelManaged aesAlg = null;
// Declare the string used to hold
// the decrypted text.
string plaintext;
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.None, KeySize = 256, BlockSize = 128, Key = key, IV = iv };
// Create a decrytor 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();
srDecrypt.Close();
}
}
}
return plaintext;
}
非常感谢任何帮助或想法。
【问题讨论】:
-
为什么你认为key是64字节?对我来说,它看起来像 32。
-
请注意,十六进制编码每个字节使用 两个 个字符,因此如果您将 32 字节的密钥编码为十六进制,它将产生一个 64 个字符的字符串。
-
但是,您的填充不正确。
openssl_decrypt默认使用 PKCS#7-padding,但在 C# 中,您完全禁用了填充。您需要设置Padding = PaddingMode.PKCS7。
标签: c# php encryption