PHP相当于.net AES加密

我正在与客户进行数据交换集成,他们发送给我的数据使用他们的C# encrypt方法encrypt (如下)。

我的应用程序正在运行PHP 5.3,我需要一个等效的代码来解密他们发送的数据。 我有PHP代码,但它不能正确解密客户端数据。

显然,我在加密/解密方法,IV键或其他方面犯了一些错误。 谁能发现错误?

谢谢。

C#代码(来自我的客户):

 using System; using System.Security.Cryptography; using System.Text; using System.IO; public class Program { public static void Main() { var text = "this is a plain string"; var enc = Program.Encrypt(text); Console.WriteLine(enc); Console.WriteLine(Program.Decrypt(enc)); } public static string Encrypt(string clearText) { var EncryptionKey = "1234567890123456"; byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); using (Aes encryptor = Aes.Create()) { byte[] IV = new byte[15]; var rand = new Random(); rand.NextBytes(IV); Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, IV); encryptor.Key = pdb.GetBytes(32); encryptor.IV = pdb.GetBytes(16); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(clearBytes, 0, clearBytes.Length); cs.Close(); } clearText = Convert.ToBase64String(IV) + Convert.ToBase64String(ms.ToArray()); } } return clearText; } public static string Decrypt(string cipherText) { var EncryptionKey = "1234567890123456"; byte[] IV = Convert.FromBase64String(cipherText.Substring(0, 20)); cipherText = cipherText.Substring(20).Replace(" ", "+"); byte[] cipherBytes = Convert.FromBase64String(cipherText); using (Aes encryptor = Aes.Create()) { Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, IV); encryptor.Key = pdb.GetBytes(32); encryptor.IV = pdb.GetBytes(16); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherBytes, 0, cipherBytes.Length); cs.Close(); } cipherText = Encoding.Unicode.GetString(ms.ToArray()); } } return cipherText; } } 

PHP代码我有:

 public function encrypt($plainText) { $secretKey = '1234567890123456'; return rtrim( base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_256, $secretKey, $plainText, MCRYPT_MODE_ECB, mcrypt_create_iv( mcrypt_get_iv_size( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB ), MCRYPT_RAND) ) ), "\0" ); } public function decrypt($encodedData) { $secretKey = '1234567890123456'; return rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_256, $secretKey, base64_decode($encodedData), MCRYPT_MODE_ECB, mcrypt_create_iv( mcrypt_get_iv_size( MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB ), MCRYPT_RAND ) ), "\0" ); } 

谁能发现错误?

是的,并且最重要的不是你的错: mcrypt令人困惑的API再次罢工 。

也就是说,这里实际上存在多处错误。

 return rtrim( // unnecessary base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_256, // Not AES $secretKey, $plainText, MCRYPT_MODE_ECB, // BAD, use MCRYPT_MODE_CBC or 'ctr' instead mcrypt_create_iv( mcrypt_get_iv_size( // unless you're going make this MCRYPT_RIJNDAEL_256, // configurable, you should just MCRYPT_MODE_ECB // hard-code this as an integer ), MCRYPT_RAND) // BAD, use MCRYPT_DEV_URANDOM ) ), "\0" ); 

如果您要生成IV,则应进行通信,以便您的收件人可以成功解密相同的第一个块。 C#代码执行此操作,而PHP则没有。

从加密工程的角度来看,您应该考虑在C#land和PHP中部署Encrypt然后Authenticate协议。 请参阅有关加密和身份validation的博文 。 此外, 您编写的所有加密代码可能都已损坏 。

似乎PHP脚本使用错误的模式:
https://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.mode%28v=vs.110%29.aspx
C#function不设置任何模式,因此默认值为CBC。
PHP部分使用ECB,这不仅错误,而且不安全。