无法使 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 方案。