dongmanzui8486 2019-04-16 16:50
浏览 87

如何使用cert发送SOAP数字签名消息

I want to sign an XML document using certificate. It should looks like:

<soapenv:Envelope xmlns:obs="http://csioz.gov.pl/zsmopl/ws/obslugakomunikatow/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" wsu:Id="X509-UUU09456789100000">XXXX==</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="obs soapenv" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#id-XYZXYZ1234567890000"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="obs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>vVYVY4CXo60TYkSZ8S/LQJo/8Zc=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>SIGNATURExxxx</ds:SignatureValue><ds:KeyInfo><wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"><wsse:Reference URI="#X509-UUU09456789100000" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"/></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soapenv:Header>
   <soapenv:Body wsu:Id="id-XYZXYZ1234567890000" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <obs:zapiszKomunikatOS>

          <komunikatOS>
              ...
          </komunikatOS>

      </obs:zapiszKomunikatOS>
   </soapenv:Body>
</soapenv:Envelope>

I've tried to use an XMLSecLibs but unfortunatelly it doesn't work well. The first, I don't know how to add inclusive-namespaces with that tool and maybe that is the key for properly signing? I also tried to copy the digest value and signature value with changing the references to above template, but it doesn't work (I've got message from SOAP server: "A security error was encountered when verifying the message Caused by: The signature or decryption was invalid").

There is some ugly code tries to sign:

$communicateFile = __DIR__ . 'template-3.xml';
$pemFilePrv = __DIR__ . '/../cert/15.pem';
$xml = trim(file_get_contents($communicateFile));

$wsseNamespace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
$wsuNamespace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd';

$doc = new \DOMDocument();
$doc->load($communicateFile);

$xp = new \DOMXPath($doc);

$xp->registerNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/'); 

$xp->registerNamespace('wsse',$wsseNamespace);
$xp->registerNamespace('wsu',$wsuNamespace);
$xp->registerNamespace('ds',XMLSecurityDSig::XMLDSIGNS);

$securityNode = $xp->query('//wsse:Security')->item(0);
$bodyNode = $xp->query('//soapenv:Body')->item(0);

$objDSig = new XMLSecurityDSig();
$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$objDSig->addReference($bodyNode, XMLSecurityDSig::SHA1,NULL, 
    array('prefix'=>'wsu','prefix_ns'=>$wsuNamespace)); 

$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'private'));
$objKey->passphrase = 'XXXXX';
$objKey->loadKey($pemFilePrv, TRUE);
$objDSig->sign($objKey);

$objDSig->insertSignature($securityNode);

Could anyone help me? Maybe there is only missing an incluseNamespaces? I count on you, becouse I'm out of ideas..

Best Regards

  • 写回答

1条回答 默认 最新

  • 普通网友 2019-04-16 17:34
    关注

    This example is a project of its own that is in production. I hope I can help you.

    $context = stream_context_create([ 
        'ssl' => [ 
            'verify_peer' => false, 
            'verify_peer_name' => false, 
            'local_cert' =>  LOCAL_CERT, 
            'passphrase' => PRIVATE_KEY_PASSPHRASE 
        ] 
    ]); 
    
    $client = new BinarySignedSoapClient($wsdl , ['trace' => 1, 'stream_context' => $context]); 
    

    Call to:

    class BinarySignedSoapClient extends \SoapClient 
    { 
    
        function __construct($wsdl, $context, $params) { 
          $this->crt_cert_file = array_key_exists('crt_cert_file', $params) ? $params['crt_cert_file'] : null; 
          $this->private_key_passphrase = array_key_exists('private_key_passphrase', $params) ? $params['private_key_passphrase'] : null; 
          $this->private_key_file = array_key_exists('private_key_file', $params) ? $params['private_key_file'] : null; 
          parent::__construct($wsdl, $context); 
        } 
    
        public function __doRequest($request, $location, $saction, $version, $one_way = 0) 
        { 
    
            $doc = new \DOMDocument('1.0'); 
            $doc->loadXML($request); 
    
            $objWSSE = new \WSSESoap($doc); 
    
            /* add Timestamp with no expiration timestamp */ 
            $objWSSE->addTimestamp(); 
    
            /* create new XMLSec Key using RSA_SHA1 and type is private key */ 
            $objKey = new \XMLSecurityKey(\XMLSecurityKey::RSA_SHA1, ['type' => 'private']); 
    
            /* load the private key from file - last arg is bool if key in file (true) or is string (false) */ 
            $objKey->passphrase = $this->private_key_passphrase; 
            $objKey->loadKey(__DIR__ ."/../localssl/". $this->private_key_file, true, false); 
    
            /* Sign the message - also signs appropiate WS-Security items */ 
            $options = array("insertBefore" => false); 
            $objWSSE->signSoapDoc($objKey, $options); 
    
            /* Add certificate (BinarySecurityToken) to the message */ 
            $token = $objWSSE->addBinaryToken(file_get_contents(__DIR__ ."/../localssl/". $this->crt_cert_file)); 
    
            /* Attach pointer to Signature */ 
            $objWSSE->attachTokentoSig($token); 
            $retVal = parent::__doRequest($objWSSE->saveXML(), $location, $saction, $version); 
    
            $doc = new \DOMDocument(); 
            $doc->loadXML($retVal); 
    
            $options = ["keys" => ["private" => ["key" => __DIR__ . $this->private_key_file, "isFile" => true, "isCert" => false]]]; 
            $objWSSE->decryptSoapDoc($doc, $options); 
    
    
            return $doc->saveXML(); 
    
        } 
    } 
    
    评论

报告相同问题?

悬赏问题

  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题