XML数字签名。如何使用签名者gem将ds命名空间添加到Signature节点?

时间:2016-08-19 13:38:51

标签: ruby xml nokogiri xml-signature signer

我需要在soap消息中包含xml,从原始xml中消化数据并对其进行签名。实际的签名或摘要算法暂时无关紧要。

原始xml示例:

<TransferMsg>
   <Data>Super Important Data</Data>
</TransferMsg>

最终结果必须是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 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">
    <soap:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-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#X509v3" wsu:Id="CertId">MIIIRzCCB/agAwIBAgIKSchnBgAAAAGKvDAIBgYqhQMCAgMwggFOMRgwFgYFKoUDZAESDTEwMjc3MDcwMTM4MDYxGjAYBggqhQMDgQMBARIMMDA3NzA3MzE0MDI5MTwwOgYDVQQJDDPQkS7QodGD0YXQsNGA0LXQstGB0LrQuNC5INC/0LXRgCzQtDExLNGB0YLRgDEs0L7RhDYxIzAhBgkqhkiG9w0BCQEWFGUtbW9za3ZhQGUtbW9za3ZhLnJ1MQswCQYDVQQGEwJSVTEcMBoGA1UECAwTNzcg0LMuINCc0L7RgdC60LLQsDEVMBMGA1UEBwwM0JzQvtGB0LrQstCwMTUwMwYDVQQKDCzQntCQ0J4gItCt0LvQtd=</wsse:BinarySecurityToken>
            <ds:Signature>
                <ds:SignedInfo>
                    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
                </ds:SignedInfo>
                <ds:SignatureValue>vnjz04yWa7DbRtC5vJAt/tsCR5m31i3e8FMxG2eOIo4DtsGhm1FgZ8wKLEEzvbYuolrosc2OKkFafqJinsTWsg==</SignatureValue>
                <ds:KeyInfo>
                    <wsse:SecurityTokenReference>
                        <wsse:Reference URI="#CertId" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
            </Signature>
        </wsse:Security>
    </soap:Header>
    <soap:Body wsu:Id="body">
        <soap:TransferMsg>
            <soap:DataToDigest>Super Important Data</soap:DataToDigest>
        </soap:TransferMsg>
    </soap:Body>
</soap:Envelope>

现在我正在使用signer内置sign!digest!这样的方法:

require 'openssl'
require 'signer'

class MySigner
  def initialize
    @soap_envelope = File.open('./data/soap_envelope.xml') { |f| Nokogiri::XML(f) }
  end

  def sign(xml_to_sign)
    signer = Signer.new(put_in_envelope(xml_to_sign))
    signer.cert = OpenSSL::X509::Certificate.new(File.read("./data/cert.pem"))
    signer.private_key = OpenSSL::PKey.read(File.read("./data/key.pem"), "PASSWORD")
    signer.security_token_id = 'CertId'

    namespaces = {
      'soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
      'ds' => 'http://www.w3.org/2000/09/xmldsig#'
    }

    # Digest soap:Body tag
    signer.document.xpath('//TransferMsg', namespaces).each do |node|
      signer.digest!(node, id: 'body')
    end

    # Sign document itself
    signer.sign!(security_token: true, enveloped: true)

    signer.to_xml
  end

  def put_in_envelope(xml)
    xml_object = Nokogiri::XML(xml)
    valuable_data = xml_object.xpath('/TransferMsg').to_s
    @soap_envelope.xpath('//soap:Body').children.first.add_next_sibling(valuable_data)
    @soap_envelope
  end
end  

soap_envelope.xml:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                   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"
                   xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    </wsse:Security>
  </soap:Header>
  <soap:Body wsu:Id="body">
  </soap:Body>
</soap:Envelope>

但结果代码有<Signature xmlns='http://www.w3.org/2000/09/xmldsig#'>而不是<ds:Signature>

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 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">
    <soap:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-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#X509v3" wsu:Id="CertId">MIIIRzCCB/agAwIBAgIKSchnBgAAAAGKvDAIBgYqhQMCAgMwggFOMRgwFgYFKoUDZAESDTEwMjc3MDcwMTM4MDYxGjAYBggqhQMDgQMBARIMMDA3NzA3MzE0MDI5MTwwOgYDVQQJDDPQkS7QodGD0YXQsNGA0LXQstGB0LrQuNC5INC/0LXRgCzQtDExLNGB0YLRgDEs0L7RhDYxIzAhBgkqhkiG9w0BCQEWFGUtbW9za3ZhQGUtbW9za3ZhLnJ1MQswCQYDVQQGEwJSVTEcMBoGA1UECAwTNzcg0LMuINCc0L7RgdC60LLQsDEVMBMGA1UEBwwM0JzQvtGB0LrQstCwMTUwMwYDVQQKDCzQntCQ0J4gItCt0LvQtd=</wsse:BinarySecurityToken>
            <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                <SignedInfo>
                    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
                </SignedInfo>
                <SignatureValue>vnjz04yWa7DbRtC5vJAt/tsCR5m31i3e8FMxG2eOIo4DtsGhm1FgZ8wKLEEzvbYuolrosc2OKkFafqJinsTWsg==</SignatureValue>
                <KeyInfo>
                    <wsse:SecurityTokenReference>
                        <wsse:Reference URI="#CertId" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
                    </wsse:SecurityTokenReference>
                </KeyInfo>
            </Signature>
        </wsse:Security>
    </soap:Header>
    <soap:Body wsu:Id="body">
        <soap:TransferMsg>
            <soap:DataToDigest>Super Important Data</soap:DataToDigest>
        </soap:TransferMsg>
    </soap:Body>
</soap:Envelope>

当然我可以手动更改Signature节点命名空间并使用nokogiri删除xmlns,但我更喜欢更自动的方式来执行此操作。我在文档中遗漏了什么吗?

0 个答案:

没有答案