【问题标题】:Decrypt data using PHP that was encrypted with Rijndael (C#)使用通过 Rijndael (C#) 加密的 PHP 解密数据
【发布时间】:2020-01-29 10:19:25
【问题描述】:

我的任务是使用 PHP 解密 C# 中加密的数据。我尝试使用 phpseclib 库。所以这里是 C# 中用于加密的现有代码:

    public static String EncryptMyText(string clearText, string Password)
    {
        if (clearText.Length == 0) return "";
        byte[] clearBytes = System.Text.Encoding.UTF8.GetBytes(clearText);
        // second parameter is "Ivan Medvedev" in string
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
        return Convert.ToBase64String(encryptedData);
    }

    public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
    {
        try
        {
            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();
            alg.Key = Key;
            alg.IV = IV;
            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(clearData, 0, clearData.Length);
            cs.Close();
            byte[] encryptedData = ms.ToArray();
            return encryptedData;
        }
        catch (Exception ex)
        {
            string message = ex.Message;
        }
        return null;
    }

    EncryptMyText("sometext", "xxxxxxxxxxxxxxx"); // password have 15 characters length

无法更改此代码。所以这是我尝试使用 phpseclib 的方法:

$key = "xxxxxxxxxxxxxxx";
$salt = "Ivan Medvedev";
$cipher = new Rijndael();
$cipher->setPassword($cle, 'pbkdf1', 'sha1', $salt);
$cipher->decrypt(base64_decode("someCryptedText"));

此时,代码因setPassword() 调用引发的异常“派生密钥太长”而中断。

我尝试了很多方法,例如更改 blockLengthKeyLenghth 而不使用 setPassword()

$cipher->setKeyLength(256);
$cipher->setBlockLength(128);

没有明显变化。

我在解密和密码方面几乎没有经验,所以我挖掘了一些有关使用的 C# 代码的信息。在这里查看 Rijndael 课程https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8。我尝试了几件事,但对我应该看的东西没有太多想法。我什至不知道是否有可能使用 Phpseclib 来解密这段 C# 代码生成的数据。

感谢所有能给我一些指导的人。

【问题讨论】:

    标签: c# php phpseclib rijndael


    【解决方案1】:

    看起来https://github.com/phpseclib/phpseclib/issues/1447#issuecomment-580594929 可能会回答您的问题。引用它:

    根据https://crypto.stackexchange.com/q/22271/4520 PasswordDeriveBytes 实现了 PBKDF1 的定制版本。

    试试这个:

    function pbkdf1ms(&$cipher, $password, $hash, $salt, $rounds)
    {
        $keyLength = $cipher->getKeyLength() >> 3;
        $blockLength = $cipher->getBlockLength() >> 3;
    
        $dkLen = $keyLength + $blockLength;
    
        $hashObj = new Hash();
        $hashObj->setHash($hash);
        if ($dkLen > 100 * $hashObj->getLength()) {
            user_error('Derived key too long');
            return false;
        }
    
        $t = $password . $salt;
        for ($i = 0; $i < $rounds; ++$i) {
            $old = $t;
            $t = $hashObj->hash($t);
        }
    
        $ctr = 1;
        while ($dkLen > strlen($t)) {
            $t.= $hashObj->hash($ctr++ . $old);
        }
    
        $key = substr($t, 0, $dkLen);
    
        $cipher->setKey(substr($key, 0, $keyLength));
        //$cipher->setKey(substr($key, $keyLength));
        $remainingBytes = $hashObj->getLength() - $keyLength % $hashObj->getLength();
        $cipher->setIV(
            substr($key, $remainingBytes, $blockLength - $remainingBytes) .
            substr($key, $keyLength + $remainingBytes)
        );
    }
    
    $c = new Rijndael;
    $c->setKeyLength(256);
    pbkdf1ms($c, 'xxxxxxxxxxxxxxx', 'sha1', 'Ivan Medvedev', 100);
    
    $c->decrypt(base64_decode("s@omeCryptedText"));
    

    【讨论】:

    • 是的,我是 github 问题的作者,terrafrost 评论几乎回答了这个问题 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 2011-05-18
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多