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

Sta*_*nov 2 .net php 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)
Run Code Online (Sandbox Code Playgroud)

现在,这是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);
Run Code Online (Sandbox Code Playgroud)

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

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

Luk*_*ark 5

您的代码无效,因为:

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

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

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