【问题标题】:Decrypt C# RIJNDAEL encoded text in PHP在 PHP 中解密 C# RIJNDAEL 编码的文本
【发布时间】:2015-04-22 10:10:39
【问题描述】:

作为授权过程的一部分,我需要解密一个字符串。

文档指定授权字符串使用以下设置加密:

  • 输入数据的填充:PKCS*7
  • 密码字节数组的长度为 32 个字节。密码字符串被转换为 UTF-16 编码的字节数组,然后用零填充字节数组,最长为 32 个字节。较长的密码会被截断。

C# 示例:

    /// <summary>
    /// Decrypts a string.
    /// </summary>
    /// <param name="content">The string to decrypt.</param>
    /// <param name="password">The password to use.</param>
    /// <returns>The decrypted string.</returns>
    private static string DecryptString(string content, string password)
    {
        Rijndael aes;
        byte[] retVal = null;
        byte[] contentBytes;
        byte[] passwordBytes;
        byte[] ivBytes;

        try
        {
            contentBytes = Convert.FromBase64String(content);

            //Create the password and initial vector bytes
            passwordBytes = new byte[32];
            ivBytes = new byte[16];
            Array.Copy(Encoding.Unicode.GetBytes(password), passwordBytes, Encoding.Unicode.GetBytes(password).Length);
            Array.Copy(passwordBytes, ivBytes, 16);

            //Create the cryptograpy object
            using (aes = Rijndael.Create())
            {
                aes.Key = passwordBytes;
                aes.IV = ivBytes;
                aes.Padding = PaddingMode.PKCS7;

                //Decrypt
                retVal = aes.CreateDecryptor().TransformFinalBlock(contentBytes, 0, contentBytes.Length);
            }
        }
        catch
        {
        }

        return Encoding.Unicode.GetString(retVal);
    }

这里讨论了相同的功能,但对于 JAVA:Decrypt C# RIJNDAEL encoded text

我尝试使用以下函数对其进行解密,但结果与预期不同:

function decrypt($string, $pass){
    $iv = substr($pass, 0, 16);
    $data =  mcrypt_decrypt(MCRYPT_RIJNDAEL_256,
                        $pass,
                        base64_decode($string),
                        MCRYPT_MODE_CBC,
                        $iv);
    $pad = ord($data[strlen($data) - 1]);
    return substr($data, 0, -$pad);
}

加密后的字符串"7iTdZnp0DtGnIfwwqY4W/glbLLVZ0+asVLAuz13PzrW0wM6HC7rNuQvcG8JDSehyYeBJARdXHgLo9hRL9sBz3fN5LJ8cro3o0kFnAao2YRU="

应该解密为

"ldYWMFlSbcki6LMl3rkNfGavnt8VqmZd" 

使用密码"GAT"

我觉得跟密码/iv/encoding有关

【问题讨论】:

  • 您没有展示如何编码 $pass :-)
  • 但是我可以确认阻塞模式是CBC,所以MCRYPT_MODE_CBC是对的。
  • 这是我没有得到的部分:Password string is converted to UTF-16 encoded byte array and byte array is then padded with zeroes up to length of 32 bytes. 对于 mcrypt_decrypt,对于 php 手册解释的密钥 - If it's smaller than the required keysize, it is padded with '\0'. 在 mcrypt_decrypt 中使用之前我应该​​如何编码密码?跨度>
  • 您只需要对 UTF16 进行编码,如有必要,将其剪切为 32 个字节
  • 已经试过了:$password = mb_convert_encoding('GAT', 'utf-16le');

标签: c# php encryption


【解决方案1】:
function decrypt($string, $pass)
{
    $encodedPass = mb_convert_encoding($pass, 'utf-16le');
    $encodedPass = substr($encodedPass, 0, 32);
    $encodedPass = str_pad($encodedPass, 32, "\0", STR_PAD_RIGHT);
    $iv = substr($encodedPass, 0, 16);

    $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
                        $encodedPass,
                        base64_decode($string),
                        MCRYPT_MODE_CBC,
                        $iv);
    $pad = ord($data[strlen($data) - 1]);
    return substr($data, 0, -$pad);
}

在 PHP 中,MCRYPT_RIJNDAEL_128/MCRYPT_RIJNDAEL_256 不是键的大小,而是块的大小(参见https://www.chilkatsoft.com/p/php_aes.asp)。 C# 通常使用 16 字节块,所以 MCRYPT_RIJNDAEL_128。密钥的大小是自动检测的。请注意,我已将密码的编码/调整大小移到方法中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2011-03-26
    相关资源
    最近更新 更多