Openssl 在PHP中验证RSA-SHA256 xml(登录.NET并在PHP中验证)

Openssl 在PHP中验证RSA-SHA256 xml(登录.NET并在PHP中验证),openssl,cryptography,rsa,php-openssl,rsa-sha256,Openssl,Cryptography,Rsa,Php Openssl,Rsa Sha256,我收到XML请求,包含MsgBody标记和签名(签名过程在.net中完成) 我必须验证他们发送的消息正文、签名和请求者公钥,但我不能 我的代码是: $msg_body = "<MsgBody><Transactions>....</Transactions></MsgBody>"; $signature = "nkI/Z/ySJSxarh..............=="; $verifying_flag =

我收到XML请求,包含MsgBody标记和签名(签名过程在.net中完成)

我必须验证他们发送的消息正文、签名和请求者公钥,但我不能

我的代码是:

$msg_body = "<MsgBody><Transactions>....</Transactions></MsgBody>";
$signature = "nkI/Z/ySJSxarh..............==";
$verifying_flag = openssl_verify($msg_body, base64_decode($signature), PUBLIC_KEY, OPENSSL_ALGO_SHA256);
$Verification_标志在两个方面都失败

此代码在.NET中完成的签名过程:

using System;

public class Program
{
    public static string SignMessage(XElement xmlMessage, Collection<string> xPaths, string certificateSerialNumber)
    {
        string elementsValue = string.Empty;
        foreach (vara xPath in xpaths)
        {
            IEnumerable<XElement> xPathSelectElements = xmlMessage.XPathSelectElements(xPath);
            foreach (XElement xPathSelectElements in xPathSelectElements)
            {
                elementsValue += xPathSelectElements.ToString();
            }
        }

        RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
        rsaCryptoServiceProvider.FromXmlString(GetCertificates(certificateSerialNumber).PrivateKey.ToXmlString(true));
        RSACryptoServiceProvider.UseMachineKeyStore = true;
        rsaCryptoServiceProvider.ExportParameters(false);
        rsaCryptoServiceProvider.KeySize = 2048;
        return Convert.ToBase64String(rsaCryptoServiceProvider.SignData(Encoding.Unicode.GetBytes(elementsValue), CryptoConfig.MapNameToOID("SHA256")));
    }
使用系统;
公共课程
{
公共静态字符串SignMessage(XElement xmlMessage、集合XPath、字符串证书SerialNumber)
{
string elementsValue=string.Empty;
foreach(xpaths中的vara xPath)
{
IEnumerable xPathSelectElements=xmlMessage.xPathSelectElements(xPath);
foreach(xPathSelectElements中的XElement xPathSelectElements)
{
elementsValue+=xPathSelectElements.ToString();
}
}
RSACryptoServiceProvider RSACryptoServiceProvider=新的RSACryptoServiceProvider();
rsacyptoServiceProvider.FromXmlString(GetCertificates(certificateSerialNumber).PrivateKey.ToXmlString(true));
rsacryptServiceProvider.UseMachineKeyStore=true;
rsacryptserviceprovider.ExportParameters(false);
rsacryptserviceprovider.KeySize=2048;
返回Convert.ToBase64String(rsaCryptoServiceProvider.SignData(Encoding.Unicode.GetBytes(elementsValue)、CryptoConfig.MapNameToOID(“SHA256”);
}

如何验证他们的请求?!

首先,您使用的是
SHA-256
,因此您必须在PHP端设置它:

$rsa->setHash('sha256');
其次,您必须设置签名模式以默认使用PKCS#1方案:

$rsa->setSignatureMode(CRYPT\u rsa\u SIGNATURE\u PKCS1);
最后,由于在C#上使用的是
Encoding.Unicode.GetBytes
,因此在验证之前,需要将php上的消息体转换为
UTF-16LE

$msg_body=mb_convert_编码($msg_body,'UTF-16LE');
最后,代码应该是这样的:

$rsa=new\Crypt_rsa();
$rsa->loadKey(公钥);
$rsa->setHash('sha256');
$rsa->setSignatureMode(密码\u rsa\u签名\u PKCS1);
$msg_body=mb_convert_编码($msg_body,'UTF-16LE');
$verifying_flag=$rsa->verify($msg_body,base64_decode($signature));
更新 如果要在PHP上生成消息签名,可以轻松执行以下操作:

$rsa=new\Crypt_rsa();
$rsa->loadKey(私钥);
$rsa->setHash('sha256');
$rsa->setSignatureMode(密码\u rsa\u签名\u PKCS1);
$msg_body=mb_convert_编码($msg_body,'UTF-16LE');
$signature=base64_encode($rsa->sign($msg_body));
顺便说一句,您可以通过在两种方式上删除
mb\u convert\u encoding
行来避免转换消息编码(验证和签名)

using System;

public class Program
{
    public static string SignMessage(XElement xmlMessage, Collection<string> xPaths, string certificateSerialNumber)
    {
        string elementsValue = string.Empty;
        foreach (vara xPath in xpaths)
        {
            IEnumerable<XElement> xPathSelectElements = xmlMessage.XPathSelectElements(xPath);
            foreach (XElement xPathSelectElements in xPathSelectElements)
            {
                elementsValue += xPathSelectElements.ToString();
            }
        }

        RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
        rsaCryptoServiceProvider.FromXmlString(GetCertificates(certificateSerialNumber).PrivateKey.ToXmlString(true));
        RSACryptoServiceProvider.UseMachineKeyStore = true;
        rsaCryptoServiceProvider.ExportParameters(false);
        rsaCryptoServiceProvider.KeySize = 2048;
        return Convert.ToBase64String(rsaCryptoServiceProvider.SignData(Encoding.Unicode.GetBytes(elementsValue), CryptoConfig.MapNameToOID("SHA256")));
    }