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

将C#代码转换为php进行加密和解密,c#,php,encryption,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


我试图将这段代码转换为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));

您的PHP代码不会在PHP5.6上运行,因为密钥大小错误,它必须是32字节

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

作为证明,在PHP和C#中,创建一个包含32个字节(32个字符)的密钥,并直接使用这32个字节作为密钥,这样它就可以工作了


但最后,您需要一种在PHP和C上导出字节的通用方法。要最终获得一致的键控代码,可以使用SHA-256哈希生成键。

您的PHP代码不会在PHP5.6上运行,因为键大小错误,它必须是32字节

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

作为证明,在PHP和C#中,创建一个包含32个字节(32个字符)的密钥,并直接使用这32个字节作为密钥,这样它就可以工作了

但最后,您需要一种在PHP和C#上导出字节的通用方法,为了最终获得一致的键控代码,可以使用SHA-256哈希生成键

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

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

  • Rijndael支持多种块大小,但不清楚C#默认块大小是什么。如果您想要的是AES(应该是),则块大小需要为128位

  • 鉴于MSDN文档未指定默认值,最好显式设置块大小、键大小、模式和填充

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

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

  • Rijndael支持多种块大小,但不清楚C#默认块大小是什么。如果您想要的是AES(应该是),则块大小需要为128位

  • 鉴于MSDN文档未指定默认值,最好显式设置块大小、键大小、模式和填充


  • 谢谢你的信息和帮助,但是经过我的尝试到现在我不能得到正确的结果,你能给我样本代码吗?你有可能吗?我没有可用的C#,但是应该有很多这样的例子。谢谢你的信息和帮助,但是在我尝试到现在为止,我无法得到正确的结果。你能给我示例代码吗?你有可能吗?我没有可用的C#,但应该有很多这样的例子。请注意,mcrypt是弃置软件,多年来没有更新过,最好不要使用它。不要使用固定的IV。每次加密都应该随机选择它,以便实现语义安全。它不必是秘密的,所以你可以把它和密文一起发送。一种常见的方法是将其预先添加到密文中。请注意,mcrypt是弃置软件,多年未更新,最好不要使用它。不要使用固定的IV。每次加密都应随机选择它,以便实现语义安全。它不必是秘密的,所以你可以把它和密文一起发送。一种常见的方法是在密文前加上前缀。