Rijndael C#到PHP的转换给出了不同的结果

本文关键字:结果 转换 PHP Rijndael | 更新日期: 2023-09-27 17:59:26

我正在尝试将用C#编写的加密代码移植到PHP。下面的代码使用Rijndael-128加密。PHP代码给出的结果与C#代码略有不同。在不使用Salt和随机IV以及不改变C#代码的约束下。在浏览了stackoverflow上关于这个问题的许多答案并对代码进行了几次更改后,代码仍然没有产生正确的结果。

C#代码(类的成员函数)

public static string Encrypt(string plainText, string passPhrase)
{
    byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
    var password = new Rfc2898DeriveBytes(passPhrase, new byte[8], 10000);
    byte [] keyBytes= password.GetBytes(keysize / 8); //256/8
    var symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;
    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
    var memoryStream = new MemoryStream();
    var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();
    memoryStream.Close();
    cryptoStream.Close();
    return Convert.ToBase64String(cipherTextBytes);
}

PHP代码(类的成员函数)

public function encrypt(){
    $plainText="Same_input_as_above";
    $plainText=mb_convert_encoding($plainText,'UTF-8');
    $passPhrase=mb_convert_encoding($this->secret,'UTF-8');
    $salt=str_pad("",8,"'0");
    $key= hash_pbkdf2 ( 'sha1' , $passPhrase, $salt , 10000 ,self::KEYSIZE/8, true);
    $initVector=mb_convert_encoding(self::INITVECTOR,'UTF-8');
    $tempCipher= mcrypt_encrypt (MCRYPT_RIJNDAEL_128 , $key , $plainText , MCRYPT_MODE_CBC,$initVector);
    return base64_encode($tempCipher);
}

C#输出

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhJYr8mt3HxfYza4bjkV8gtq

PHP输出

O/Fi4tfdS5APen6YAboRnr%2B2bSrHSG71OHhX7YZbbhIpdOLx9oscZnlAdyTMgeGX

C#的解密函数与自己创建的密码配合良好,但在解码PHP生成的密码时会出现Padding is invalid and cannot be removed.错误。

Rijndael C#到PHP的转换给出了不同的结果

问题是mcrypt只支持非标准的null填充。C#库支持标准的PKCS#7(née PKCS#5)填充。请参阅PKCS#7填充。

在PHP:中,您可以在加密前和解密后轻松添加和删除PKCS#7填充

添加PKCS#7填充

$padLength = $blockSize - (strlen($clearText) % $blockSize);
$clearText = $clearText . str_repeat(chr($padLength), $padLength);

剥去PKCS#7填充

$padLength = ord($cryptText[strlen($cryptText)-1]);
$cryptText = substr($cryptText, 0, strlen($cryptText) - $padLength);

更好的解决方案是不使用mcrypt。选项包括decapse或RNCryptor,它们提供了一个完整的解决方案。