将 C# 代码转换为 php 以进行加密和解密


convert C# code to php for encrypt and decrypt


我尝试将此代码转换为 php,但我不能,而且总是在 C# 和 PHP 中得到不同的结果这是我用于加密和解密的 C# 代码:

private static readonly byte[] initVectorBytes = Encoding.ASCII.GetBytes("1234567812345678");
private const int keysize = 256;
private string pass = "sample";
public static string Encrypt(string plainText, string passPhrase)
{
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
    PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
    byte[] keyBytes = password.GetBytes(keysize / 8);
    RijndaelManaged symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;
    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
    MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();
    return Convert.ToBase64String(cipherTextBytes);
}
public static string Decrypt(string cipherText, string passPhrase)
{
    byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
    PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
    byte[] keyBytes = password.GetBytes(keysize / 8);
    RijndaelManaged symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;
    ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
    MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
    CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
    byte[] plainTextBytes = new byte[cipherTextBytes.Length];
    int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
    return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}

这是我的PHP代码:

$iv = "1234567812345678";
$out = null;
$key = "sample";
foreach ($iv as $i) { $out .= chr(ord(substr($i,0,1))); }
$res = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, implode($out));
  1. 键不一样。C# 正在使用 PasswordDeriveBytes 扩展密钥,这是一个很好的方法。PHP mcrypt 正在用 null 扩展他们的键。您需要相同的扩展(256 位)密钥。

  2. 填充不一样。未加密的数据必须是块大小的倍数(AES 为 128 位),如果并不总是如此,则必须添加填充。C# 未指定任何填充,并且期望数据是块大小(128 位)的倍数。默认情况下,PHP 将添加非标准的空填充,不适用于二进制数据。您需要添加常用填充,标准是PKCS#7(又名PKCS#5),请参阅PKCS#7填充。C#支持PKCS#5,但对于mcrypt,你必须在你的代码中这样做(mcrypt开发人员是Bozos,不提供标准填充)。

  3. Rijndael 支持多种 bock 大小,目前尚不清楚 C# 默认块大小是多少。如果你想要的是AES(应该是),块大小需要为128位。

  4. 鉴于 MSDN 文档未指定默认值,最好显式设置块大小、密钥大小、模式和填充。

您的 PHP

代码无法在 PHP 5.6 上运行,因为密钥大小错误,它必须是 32 字节。

据说,在以前的版本中,PHP 用 ''0 填充键以达到正确的键长度,但在 C# 中,您正在创建派生字节(实际上是正确的)来为您的键获取足够的字节,这以 C# 和 PHP 上使用的不同键结束。

作为证明,创建一个具有 32 个字节(32 个字符)的密钥,并在 PHP 和 C# 中直接使用这 32 个字节作为密钥,这样它应该可以工作。

但是最后,您将需要一种通用方法来派生PHP和C#上的字节,以最终获得一致的密钥代码,例如使用SHA-256哈希生成密钥。