将.NET AES256加密代码转换为PHP



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

它返回与.NET ONE不同的1W3UvYVNKWEoFrpPZPd+Qw==。我同时尝试过AES-256-ECB和AES-128-ECB,结果总是与.NET的一个不同。

据我所知,openssl_encrypt默认情况下PKCS7填充是对吗?您能看到PHP给出不同结果的原因吗?

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

  • GetBytes in .NET返回该字符串的字节值。也就是说,您将获得一个字节阵列,长度为32(AES-256)。但是,使用H*的PHP中的pack解码一个十六进制字符串,这将为您提供长度16的键(AES-128)。这整个过程中,您不仅使用两个不同的键进行加密,而且还使用两个不同的键尺寸

修复上述内容将使您的代码正常工作,但远非安全,不应使用。如果要使代码安全,则需要:

  • 停止使用欧洲央行模式。如果可以的话,请使用GCM模式,否则使用CBC。您很可能最终会使用CBC。如果这样做,则需要将静脉注射到您的密文中,以便解密的聚会可以在解密时检索并使用它。ivs不需要秘密,它们只需要随机,因此您使用OpenSSL随机字节和GenerateIV方法很好。
  • 由于您可能会使用CBC模式,因此您需要应用HMAC来确保完整性。否则任何人都可以修改您的密文,您将不知道。应用HMAC时,始终加密 - 然后是MAC 。请记住在应用HMAC之前包括您的IV
  • 最后,我认为您实际上并不是要这样做,但切勿将字符串的ASCII值作为键。如果要从密码器创建键,则应应用KDF。PBKDF2可能是最适合的,并且在PHP和.NET中具有实现。

最新更新