C#RSA加密 -> Laravel phpseclib解密()

4

我正在使用由phpseclib生成的一对密钥,然后在C#中使用它来加密消息,并在PHP中进行解密。

公钥是:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvh4OvlS5+7Skk5Nij296
rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjC
mbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo
6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5
ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEU
askvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczni
WQIDAQAB
-----END PUBLIC KEY-----

通过https://superdry.apphb.com/tools/online-rsa-key-converter进行XML转换。

下面是用C#加密信息的步骤:

public void Synch()
    {
        string messageToSend = "123";
        
        var encryptedData = EncryptString(messageToSend);
        
        var request = new HTTPRequest(new Uri(APIUrl), HTTPMethods.Post, OnRequestFinished);

        request.AddField("message", encryptedData);
        request.FormUsage = BestHTTP.Forms.HTTPFormUsage.Multipart;

        request.Send();
    }

public byte[] EncryptBytes(string message)
    {
        // https://superdry.apphb.com/tools/online-rsa-key-converter
        string XML = "<RSAKeyValue><Modulus>vh4OvlS5+7Skk5Nij296rDAKQsxZrz+gV/MInvWqe/SAOlOf8vqs6xJsn7sd523X8m+b0Kd751UbeeDQRGjCmbQc9iwQHUFrNa0bSVnpyoc27K+cuxNdtoPG1XXRCFLKKqVJKSyB5ZPu+oQr+OIo6zYhU5jfCEYbpzPdyYqfDGJPpJv/r8F11MCBrdbvD5Z42ysTDqSxFGIfROWtDOP5ShSNcVGRQYfX3E/v8j+qy0yu2PD/W1UqNd3m6TTkUj/u1XukUMWp+tfXEdEp7IEUaskvGnBfHgJcsBp2c6kT9WxIU0ai4G8mo/2OsHprw42PBWLcJwfUeUgY3itSczniWQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        

        //get the object back from the stream
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(XML);
        
        byte[] bytesMessage = Encoding.UTF8.GetBytes(message);
        var bytesCipherText = rsa.Encrypt(bytesMessage, false);

        return bytesCipherText;
    }

public string EncryptString(string message)
    {
        string encryptedText = Convert.ToBase64String(EncryptBytes(message));
        return encryptedText;
    }

C# 向 PHP 发送的内容(加密消息,每次都会改变)是什么:
DE9e82l/lP211YQ0gDhvIcwU1dIXaN7re9+VpUYEB62yRYYnmzZfHxv+WeMHtvg5Yq15Lr4rhvQpTiMGyktxkR5wPQRQhDX74gonPIKgYYIfoqF0mswkulaiLReagcroVyd4ZFEfPxKScLXqjo3yIFLaGWVMGoh81ZwRoOUEGLCPkhsRMp1CiHecGZEmZm7VNoiOEeA5xRdO3asl5/jrbnpXeNXcU4OFV4n1hfdw8W04VHyzDU3AmkDnpfO3AHnZluGPOYpl3OYVn9bsmuqL9d02gBr0UP72vp5GxNoDZAy3tzymhdNZArN9sfBXX+QPOlK2eaFwSypGIa/SUn+erg==

在 PHP 解密方面:

Route::post('/decrypt', function (Request $request) {
    $encoded_message = $request->input('message');
    if (!empty($encoded_message)) {
        $private = RSA::loadFormat('PKCS8', file_get_contents(resource_path() . '/rsa/key.pem'), $password = false);

        try {
            $message = $private->decrypt(base64_decode($encoded_message));
            echo $message;
            }
        } catch (Exception $e) {
            return response()->json([
                'message' => 'Failed to process: '.$e->getMessage().$e->getTraceAsString(),
            ]);
        }

输出结果如下:
Response: {"message":"Failed to process: Decryption error#0 C:\\www\\laravel\\vendor\\phpseclib\\phpseclib\\phpseclib\\Crypt\\RSA\\PrivateKey.php(469):

我在这里漏掉了什么?

1个回答

5
在C#代码中,应用了PKCS#1 v1.5填充(Encrypt()的第二个参数设置为false),而phpseclib默认使用OAEPadding (这里)。
如果在PHP代码中显式指定使用PKCS#1 v1.5填充,则解密有效。
$message = $private->withPadding(RSA::ENCRYPTION_PKCS1)->decrypt(base64_decode($encoded_message));

另外,C#代码可以使用OAEPadding。但是要小心,如果在Encrypt()中将第二个参数设置为true,.NET默认情况下会同时使用SHA-1进行两次摘要。 然而,phpseclib默认情况下会应用SHA-256进行两次摘要。 因此,在C#代码中,为了与PHP代码兼容,必须显式地将两个摘要都设置为SHA256(这对于RSACryptoServiceProvider不可能,但对于RSACng是可能的;还需要使用重载的 Encrypt(),以便可以显式地设置摘要)。


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