使用RSA算法,C#加密PHP解密

3
我正在尝试在C#和PHP之间构建一个简单的RSA加密解密过程。 我已经使用phpseclib(http://phpseclib.sourceforge.net/)完成了PHP中的加密和C#中的解密。然而,我遇到了“Decryption error in C:\xampp\htdocs\Crypt\RSA.php on line 2103”错误,它在此处:

if ($lHash != $lHash2) {
        user_error('Decryption error', E_USER_NOTICE);
        return false;
    }

我使用了以下一段代码在C#中进行加密:

RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize);
        rsaCryptoServiceProvider.FromXmlString(publickey);
        int keySize = dwKeySize / 8;
        byte[] bytes = Encoding.UTF32.GetBytes(inputString);
        // The hash function in use by the .NET RSACryptoServiceProvider here is SHA1
        // int maxLength = ( keySize ) - 2 - ( 2 * SHA1.Create().ComputeHash( rawBytes ).Length );
        int maxLength = keySize - 42;
        int dataLength = bytes.Length;
        int iterations = dataLength / maxLength;
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i <= iterations; i++)
        {
            byte[] tempBytes = new byte[(dataLength - maxLength * i > maxLength) ? maxLength : dataLength - maxLength * i];
            Buffer.BlockCopy(bytes, maxLength * i, tempBytes, 0, tempBytes.Length);
            byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes, true);
            // Be aware the RSACryptoServiceProvider reverses the order of encrypted bytes after encryption and before decryption.
            // If you do not require compatibility with Microsoft Cryptographic API (CAPI) and/or other vendors.
            // Comment out the next line and the corresponding one in the DecryptString function.
            Array.Reverse(encryptedBytes);
            // Why convert to base 64?
            // Because it is the largest power-of-two base printable using only ASCII characters
            stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
        }
        string ciphertext = stringBuilder.ToString();

我的基本PHP代码来解密:

$rsa->loadKeyfromXML($privatekey);  
$ciphertext = file_get_contents('cipher.txt');
$ciphertext = base64_decode(strrev($ciphertext));

//$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);

$plaintext = $rsa->decrypt($ciphertext);

我尝试过PKC1,但在Crypt/RSA.php中出现了另一个错误。

1
好久没用了,但据我所记,我使用的是phpseclib。 - relativelyPrime
4个回答

2

太好了,我刚刚自己找到了解决方案。我在加密中更改了这一行:

byte[] bytes = Encoding.UTF32.GetBytes(inputString);  ==> byte[] bytes = Encoding.Default.GetBytes(inputString);

而且正如@Ryan所说的那样:
$ciphertext = base64_decode(strrev($ciphertext));  ==> $ciphertext = strrev(base64_decode($ciphertext));

感谢您的尝试。

0
我必须说我并没有完全理解你的问题,但似乎是关于如何在C#和PHP中结合使用RSA加密。我也曾经遇到过一些麻烦,对于所有仍然感兴趣的人,我编写了一个可以实现此功能的工作项目,C#程序和PHP脚本都创建RSA密钥并交换它们,然后进行加密通信(请参见这里)。

0

既然你在 C# 中使用了 Array.Reverse,我敢猜测 PHP 中的 strrev 是不必要的。

此外,phpseclib 的 Crypt_RSA 没有 loadKeyfromXML。你从哪里得到这个信息的?只需要使用 $rsa->loadKey() 就足够了。

最后,我猜测需要使用 PKCS1。当你使用它时,你遇到了什么错误?


是的,"$rsa->loadKey()" 也可以运行,没有任何区别。因为我把 PKCS 部分注释掉了,所以不幸地会出现同样的错误。 - relativelyPrime
你有没有尝试过不使用 strrev 函数? - neubert
是的,我也尝试过使用/不使用strrev和base64_decode。在RSA.php的同一行仍然出现错误。另外,当我使用PKCS1时,在以下行出现错误: if (ord($em[0]) != 0 || ord($em[1]) > 2) {
user_error('解密错误', E_USER_NOTICE); return false; }
- relativelyPrime

0

在 PHP 中,似乎你正在获取 Base64 编码的密文,然后尝试将其反转,再进行 Base64 解码?我认为你应该先解码它,然后再反转结果。这两个步骤并不相同。

至于这些反转是否必要,我无法说。


是的,我只是从源代码中获取了代码,所以使用了反转。对于从PHP加密的base64进行解密在C#中运行良好,因此我使用了相同的操作。 - relativelyPrime
尝试先解码再使用(或不使用)PKCS1的strrev仍然在同一行出现错误,而使用PKCS1会在“if (ord($em[0])!= 0 || ord($em[1])> 2)”处出现错误。 - relativelyPrime

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接