当前位置: 首页 > 知识库问答 >
问题:

PHP&C#兼容的Rijndael托管CBC模式,256位加密/解密

方河
2023-03-14

我曾在互联网上寻找解决问题的有效方法,但我尝试的一切都不奏效。我在两种语言之间得到了不同的结果。

在PHP中,我有以下代码:

function encrypt($Key, $strToEncrypt){
    $md5Key = md5(pack("H*", $Key));
    $md5Iv = md5($Key);

    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);

    $padding = $block - (strlen($strToEncrypt) % $block);
    $strToEncrypt .= str_repeat(chr($padding), $padding);

    $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $md5Key, $strToEncrypt, MCRYPT_MODE_CBC, $md5Iv);
    $enc2 = base64_encode($enc);

    return $enc2;
}

和C#中的以下代码:

    public string Encrypt(string strToEncrypt)
    {
        string ret;
        var pKey = PackH(_appkey);
        var md5Key = CalcMd5(pKey);
        var iv = CalcMd5(_appkey);

        var enc =Encoding.UTF8;
        var eIv = enc.GetBytes(iv);
        var eKey = enc.GetBytes(md5Key);

        using (var rij = new RijndaelManaged { BlockSize = 256, KeySize = 256, IV = eIv, Key = eKey, Mode = CipherMode.CBC, Padding = PaddingMode.Zeros})
        using (var memoryStream = new MemoryStream())
        using (var cryptoStream = new CryptoStream(memoryStream, rij.CreateEncryptor(eKey, eIv), CryptoStreamMode.Write))
        {
            using (var sw = new StreamWriter(cryptoStream))
            {
                sw.Write(strToEncrypt);

            }
            ret = Convert.ToBase64String(memoryStream.ToArray());
        }


        return ret;
    }
protected byte[] PackH(string hex)
    {
        if ((hex.Length % 2) == 1) hex += '0';
        var bytes = new byte[hex.Length / 2];
        for (var i = 0; i < hex.Length; i += 2)
        {
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        }
        return bytes;
    }
protected string CalcMd5(string textToEnc)
    {
        var sB = new StringBuilder();
        using (var mdHash = MD5.Create())
        {
            var cHash = mdHash.ComputeHash(Encoding.UTF8.GetBytes(textToEnc));

            foreach (byte t in cHash)
            {
                sB.Append(t.ToString("x2"));
            }
        }

        return sB.ToString();
    }

我有另一个CalcMd5函数,它接受一个byte[](与上面的函数类似,但没有GetBytes部分)。

需要加密的密钥和字符串在PHP和C#中都是相同的:

键:“24ACD2FCC7B20B8BD33FF45176F03061A09B729487E10D2DD38AB917”和

我试过在C#中修改填充模式,也试过在stackoverflow站点上找到的不同方法,但都不起作用。

我已经检查过,传递给mcrypt函数和RijndaelManaged函数的最终密钥和Iv是相同的,并且都是32字节大小。

奇怪的是,解密函数工作得很好(使用C#函数对PHP加密字符串进行解密,而使用PHP函数对C#加密字符串进行解密)。

会不会是编码有问题?或者是衬垫?还是我忽略了什么?

共有1个答案

曹茂材
2023-03-14

问题似乎是您的填充,在PHP端,您正在手动执行pkcs7-padding:

$padding = $block - (strlen($strToEncrypt) % $block);
$strToEncrypt .= str_repeat(chr($padding), $padding);

而在C#端,您正在使用:

Padding = PaddingMode.Zeros

要解决这个问题,您可以通过删除上面提到的两行来修改PHP代码,因为mcrypt()会自动为您执行zerobytepadding

Padding = PaddingMode.PKCS7
 类似资料:
  • 问题内容: 更新 我已经对C#代码进行了更改,因此它使用的块大小为256。但是现在,您好世界看起来像这样http://pastebin.com/5sXhMV11,我无法弄清楚应该使用rtrim()获得什么一团糟的最后。 另外,当您说IV应该是随机的时,您的意思是不要再使用一次相同的IV,否则我编码的方式错误吗? 再次感谢! 你好 我正在尝试使用在C#中加密的PHP解密字符串。我似乎无法让PHP使用

  • 我遇到的情况是,JSON在PHP的中加密,需要在JAVA中解密。 此包含正确的数据,现在已解密。 现在,问题是当我试图做同样的事情在Java它不起作用:( 这是: 我已经访问了类似的问题,如 AES-256 CBC用php加密,用Java解密,反之亦然 openssl_在java中加密256个CBC原始_数据 无法在Java和PHP之间交换使用AES-256加密的数据 名单还在继续。。。。但是运气

  • 我是密码学的新手。我的要求是对使用openssl加密/解密的文本进行解密/加密。我们在Openssl中使用的算法是aes-256-cbc。因此,我尝试在我的应用程序中实现相同的功能。到目前为止,在谷歌搜索了很多次之后,我所能做的就是。。 我的openssl命令是 我的密钥长度是32位IV是16位 Thnx...

  • 就像我说的,一切都很好,除了这个小的decypt...我搜索了谷歌和所有的东西,尝试了示例代码,但似乎我的代码有些东西不对。

  • 我希望有一个用C编写的程序,可以在没有openssl这样的大型库的帮助下,用AES-CBC对字符串进行编码/解码。 目标: 使用密码短语对字符串进行编码/解码: 因此,应用程序需要接受3个输入参数。。。 输入字符串(待编码)/或已编码字符串(待解码) 用于编码/解码字符串的密码 编码或解码指示器 我对C语言不熟悉(我可以用C#编码)。 我已经找到了https://github.com/kokke/