【问题标题】:Convert .net aes256 encryption code into php将.net aes256加密代码转换成php
【发布时间】:2016-12-07 07:11:01
【问题描述】:

下面的代码是一个简单的 .NET sn-p,输入有 test,它返回 p+cTm2VODfvQnreAl02wUQ== 作为输出。

Dim aesEncryptObj As New System.Security.Cryptography.RijndaelManaged()
Dim encoder As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding()

Dim tempKey As Byte() = encoder.GetBytes("00000011111111111111111111111111")
aesEncryptObj.Key = tempKey
aesEncryptObj.BlockSize = 128
aesEncryptObj.Mode = System.Security.Cryptography.CipherMode.ECB
aesEncryptObj.Padding = System.Security.Cryptography.PaddingMode.PKCS7
aesEncryptObj.GenerateIV()

Dim EncryptedBytes As Byte()
Dim encryptor As System.Security.Cryptography.ICryptoTransform = aesEncryptObj.CreateEncryptor(aesEncryptObj.Key, aesEncryptObj.IV)

Using msEncrypt As New System.IO.MemoryStream()
    Using csEncrypt As New System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write)
        Using swEncrypt As New System.IO.StreamWriter(csEncrypt)
            swEncrypt.Write(txtInput.Text)
        End Using
        EncryptedBytes = msEncrypt.ToArray()
    End Using
End Using

txtOutput.Text = Convert.ToBase64String(EncryptedBytes)

现在,这里是 PHP 代码:

const ENCRYPT_METHOD = 'aes-256-ecb';

$aesKey = pack('H*', '00000011111111111111111111111111');
$ivSize = openssl_cipher_iv_length(ENCRYPT_METHOD);

$plainText = "test";

$iv = openssl_random_pseudo_bytes($ivSize);

$cipherText = openssl_encrypt(
    $plainText,
    ENCRYPT_METHOD,
    $aesKey,
    OPENSSL_RAW_DATA,
    $iv
);

$encryptedText = $iv . $cipherText;

echo base64_encode($encryptedText);

它返回 1W3UvYVNKWEoFrpPZPd+Qw==,这与 .NET 不同。我已经尝试过 aes-256-ecb 和 aes-128-ecb,结果总是与 .NET 不同。

据我所知,openssl_encrypt 默认使用 PKCS7 填充,对吗?你能看出 PHP 给出不同结果的原因吗?

【问题讨论】:

    标签: php .net encryption aes php-openssl


    【解决方案1】:

    您的代码不起作用,因为:

    • .NET 中的GetBytes 会返回该字符串的字节值。也就是说,您将获得一个长度为 32 (AES-256) 的字节数组。但是,PHP 中的 packH* 会解码一个十六进制字符串,这将为您提供长度为 16 (AES-128) 的密钥。在整个过程中,您不仅使用两个不同的密钥进行加密,而且还使用了两种不同的密钥大小

    修复上述问题将使您的代码正常工作,但它远非真正安全,不应使用。如果您想让您的代码安全,您需要:

    • 停止使用 ECB 模式。如果可以,请使用 GCM 模式,否则使用 CBC。您很可能最终会使用 CBC。如果这样做,您需要将 IV 添加到您的密文中,以便解密方可以检索它并在解密时使用它。 IV 不需要保密,它们只需要是随机的,因此使用 OpenSSL 随机字节和 GenerateIV 方法很好。
    • 由于您可能会使用 CBC 模式,因此您需要应用 HMAC 以确保完整性。否则任何人都可以修改您的密文,而您将不知道。应用 HMAC 时,始终encrypt-then-mac。请记住应用 HMAC 之前包含您的 IV。
    • 最后,我不认为你真的打算这样做,但永远不要使用字符串的 ASCII 值作为键。如果要从密码短语创建密钥,则应应用 KDF。 PBKDF2 可能是最适合的,并且在 PHP 和 .NET 中都有实现。

    【讨论】:

    • 感谢您对问题的完整分析。我将进一步调查并在当天晚些时候接受答案。
    • 你成功了!我知道 ECB 模式不安全,但我正在使用一个向我发送加密数据的闭源设备。这将是接下来要做的事情——当通信协议被验证为完全实现时,要求改变模式。再次感谢您,您拯救了我的一天,因为我对 .NET 几乎一无所知,是的,我们很可能会使用 CBC。
    • @StanimirStoyanov 乐于助人。非常感谢您向封闭源代码开发人员施压以实施更安全的方法!
    • 其实提供设备的公司真的很开明,所以不需要压力,但是是的,这很重要,而且绝对是交易刹车的事情。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    相关资源
    最近更新 更多