将.net aes256加密代码转换成php

Convert .net aes256 encryption code into php

下面的代码是一个简单的 .NET 片段,输入 test returns 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);

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

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

您的代码无法正常工作,因为:

  • GetBytes in .NET returns 你是那个字符串的字节值。也就是说,您将获得一个长度为 32 (AES-256) 的字节数组。但是,PHP 中的 packH* 解码一个十六进制字符串,这将为您提供一个长度为 16 (AES-128) 的密钥。一直以来,您不仅使用两个不同的密钥进行加密,而且还使用两个不同的密钥 sizes.

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

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