【问题标题】:Rijndael C# to PHP conversion giving different results [duplicate]Rijndael C# 到 PHP 的转换给出不同的结果[重复]
【发布时间】:2016-12-05 18:20:03
【问题描述】:

我正在尝试将用 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. 错误。

【问题讨论】:

  • 最好不要使用mcrypt,它是废弃软件,多年未更新,不支持标准PKCS#7(née PKCS#5)填充,只有非标准空填充可以'甚至不能与二进制数据一起使用。 mcrypt 有许多出色的 bugs 可以追溯到 2003 年。请考虑使用 defuseRNCryptor,它们提供了完整的解决方案并且正在维护并且是正确的。
  • @ArtjomB。谢谢。首先,我认为是在应用空填充盐后出现问题的空盐我忘记取消注释之后的纯文本填充行。

标签: c# php .net encryption


【解决方案1】:

问题是mcrypt 只支持非标准的空填充。 C# 库支持标准 PKCS#7(née PKCS#5)填充。见PKCS#7 padding

您可以在 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。选项包括提供完整解决方案的defuseRNCryptor

【讨论】:

  • 感谢您提出更好的解决方案,但在解密时不需要删除填充
猜你喜欢
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
  • 2020-12-10
  • 2018-06-04
  • 1970-01-01
  • 2017-03-23
  • 2021-12-28
  • 1970-01-01
相关资源
最近更新 更多