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

时间:2016-12-07 07:11:01

标签: php .net encryption aes php-openssl

下面的代码是一个简单的.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);

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

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

1 个答案:

答案 0 :(得分:5)

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

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

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

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