无法使 AES 加密在 PHP 和 C# 之间工作
Can't make AES encryption to be working between PHP and C#
我花了 3 天时间,试图在我的 Unity 3D 应用程序中实现简单的加密通信。问题是,php 脚本的响应给了我奇怪的字符。
这是我的 C# 代码:
private const string key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static string Decrypt(string data)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toDecrypt = Convert.FromBase64String(data);
RijndaelManaged aes = new RijndaelManaged();
aes.Key = keyArray;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.Zeros;
aes.KeySize = 128;
aes.BlockSize = 128;
ICryptoTransform cTransform = aes.CreateDecryptor();
byte[] resultBytes = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length);
return UTF8Encoding.UTF8.GetString(resultBytes);
}
private void Start()
{
StartCoroutine(test());
}
private IEnumerator test()
{
for (;;)
{
WWW www = new WWW("http://x.com/game/getInfo.php?text=" + Security.Encrypt("test"));
yield return www;
Debug.Log(Security.Decrypt(www.text));
yield return new WaitForSeconds(4f);
}
}
还有我的 php 代码:
<?php
$key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
function Encrypt($string){
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB));
}
function Decrypt($string){
return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($string), MCRYPT_MODE_ECB);
}
$toEncrypt = Decrypt($_GET['text']);
echo Encrypt(toEncrypt);
?>
每次 Debug.Log 打印另一个字符串,如 "a'�@н���:�j" 或“��e?e����\ ��V��”,而不是 "test"。我不知道为什么。我试着用 UTF8 编码,使用 openssl 方法,更改密钥长度,但我仍然收到这些奇怪的字符。
我这里有什么遗漏的吗?
您使用的不是同一把钥匙。您的 "key" 是 32 个字符的序列。对该密钥进行编码时,您会得到一个 32 字节的字节数组。这是 256 位的 "key"。当您设置 aes.KeySize = 128;
时,这会更改您想要的密钥大小,这也会生成一个完全不同的密钥 (example)。
如果您想使用 AES-256,则必须删除 aes.KeySize = 128;
。仅将 128 更改为 256 不会改变任何内容 (exmaple)。
安全注意事项:
密钥需要与随机噪声相似。您可以生成随机密钥并将其以编码形式 (Hex/Base64) 存储在源代码中,但前提是源代码或生成的可执行文件永远不会提供给其他方。
切勿使用 ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC 方案。
我花了 3 天时间,试图在我的 Unity 3D 应用程序中实现简单的加密通信。问题是,php 脚本的响应给了我奇怪的字符。
这是我的 C# 代码:
private const string key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
public static string Decrypt(string data)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toDecrypt = Convert.FromBase64String(data);
RijndaelManaged aes = new RijndaelManaged();
aes.Key = keyArray;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.Zeros;
aes.KeySize = 128;
aes.BlockSize = 128;
ICryptoTransform cTransform = aes.CreateDecryptor();
byte[] resultBytes = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length);
return UTF8Encoding.UTF8.GetString(resultBytes);
}
private void Start()
{
StartCoroutine(test());
}
private IEnumerator test()
{
for (;;)
{
WWW www = new WWW("http://x.com/game/getInfo.php?text=" + Security.Encrypt("test"));
yield return www;
Debug.Log(Security.Decrypt(www.text));
yield return new WaitForSeconds(4f);
}
}
还有我的 php 代码:
<?php
$key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
function Encrypt($string){
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB));
}
function Decrypt($string){
return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($string), MCRYPT_MODE_ECB);
}
$toEncrypt = Decrypt($_GET['text']);
echo Encrypt(toEncrypt);
?>
每次 Debug.Log 打印另一个字符串,如 "a'�@н���:�j" 或“��e?e����\ ��V��”,而不是 "test"。我不知道为什么。我试着用 UTF8 编码,使用 openssl 方法,更改密钥长度,但我仍然收到这些奇怪的字符。
我这里有什么遗漏的吗?
您使用的不是同一把钥匙。您的 "key" 是 32 个字符的序列。对该密钥进行编码时,您会得到一个 32 字节的字节数组。这是 256 位的 "key"。当您设置 aes.KeySize = 128;
时,这会更改您想要的密钥大小,这也会生成一个完全不同的密钥 (example)。
如果您想使用 AES-256,则必须删除 aes.KeySize = 128;
。仅将 128 更改为 256 不会改变任何内容 (exmaple)。
安全注意事项:
密钥需要与随机噪声相似。您可以生成随机密钥并将其以编码形式 (Hex/Base64) 存储在源代码中,但前提是源代码或生成的可执行文件永远不会提供给其他方。
切勿使用 ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC 方案。