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

时间:2016-02-29 10:44:34

标签: c# php encryption


我尝试将此代码转换为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));

2 个答案:

答案 0 :(得分:0)

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

说,在以前的版本中,PHP使用\ 0填充键以达到正确的密钥长度,但是在C#中,您要创建派生字节(确实是正确的)以获取足够的字节用于密钥,其结束于C#和PHP上使用的不同键。

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

但最后你需要一种通用的方法来导出PHP和C#上的字节,最终得到一致的键控代码,例如可以使用SHA-256哈希生成密钥。

答案 1 :(得分:0)

  1. 键不一样。 C#使用PasswordDeriveBytes扩展密钥,这是一个很好的方法。 PHP mcrypt正在使用null来扩展它们的键。您需要扩展(256位)密钥才能相同。

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

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

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