我尝试将此代码转换为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));
答案 0 :(得分:0)
您的PHP代码将无法在PHP 5.6上运行,因为密钥大小错误,它必须是32个字节。
说,在以前的版本中,PHP使用\ 0填充键以达到正确的密钥长度,但是在C#中,您要创建派生字节(确实是正确的)以获取足够的字节用于密钥,其结束于C#和PHP上使用的不同键。
作为证据,创建一个32字节(32个字符)的密钥,并直接使用这些32字节作为密钥,在PHP和C#中,这样它应该可以工作。
但最后你需要一种通用的方法来导出PHP和C#上的字节,最终得到一致的键控代码,例如可以使用SHA-256哈希生成密钥。
答案 1 :(得分:0)
键不一样。 C#使用PasswordDeriveBytes
扩展密钥,这是一个很好的方法。 PHP mcrypt正在使用null来扩展它们的键。您需要扩展(256位)密钥才能相同。
填充不一样。未加密的数据需要是块大小的倍数(AES为128位),并且如果不总是必须添加填充。 C#没有指定任何填充,并且期望数据是块大小的倍数(128位)。默认情况下,PHP会添加非填充的空填充,并且不适用于二进制数据。您需要添加常用填充,标准是PKCS#7(又名PKCS#5),请参阅PKCS#7 padding。 C#支持PKCS#5但是对于mcrypt,你必须在你的代码中执行它(mcrypt开发人员是Bozos并且没有提供标准填充)。
Rijndael支持多种bock大小,目前尚不清楚C#默认块大小是多少。如果您想要的是AES(它应该是),则块大小需要为128位。
鉴于MSDN文档未指定默认值,最好明确设置块大小,密钥大小,模式和填充。