I am working on a data exchange integration with my client and the data they send me is encrypted using their C# encrypt
method (below).
My app is running PHP 5.3 and I need an equivalent code to decrypt the data they send. I have the PHP code but it'd not decrypt the client data correctly for me.
Clearly I am making some mistake in my encryption/decryption methods, IV key or something. Can anyone spot the mistake?
Thanks.
C# Code (From my client):
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 Code I have:
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"
);
}
Can anyone spot the mistake?
Yes, and the big one isn't really your fault: mcrypt's confusing API strikes again.
That said, there are actually multiple mistakes here.
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"
);
If you're going to generate an IV, it should be communicated so your recipient can decrypt the same first block successfully. The C# code does this, the PHP does not.
From a cryptography engineering perspective, you should consider, both in C# land and in PHP, deploying an Encrypt then Authenticate protocol. See this blog post on encryption and authentication. Also, all the crypto code you've ever written is probably broken.
It seems like the PHP Script is Using the wrong Mode:
https://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.mode%28v=vs.110%29.aspx
The C# Functions do not set any Mode so the default is CBC.
The PHP part uses ECB instead, which is not only wrong, but insecure.
来源:https://stackoverflow.com/questions/32884203/php-equivalent-of-net-aes-encryption