Как программно использовать .NET C # для соответствия SignatureValue, сгенерированному SOAPUI - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть проект SOAPUI, который использует клиентский сертификат X509 для цифровой подписи метки времени в заголовке SOAP. Мне нужно программно создать цифровую подпись в сообщениях SOAP, отправляемых на сервер с использованием .NET (без использования WCF).

SOAPUI-сгенерированное SOAP-сообщение:

    <soap:Envelope xmlns:cmaw="http://estarstation.com/cmaWS/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://estarstation.com/xsd">
  <soap:Header>
    <wsse:Security soap:mustUnderstand="1" 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:UsernameToken wsu:Id="UsernameToken-0EDE7F54075E85BDF615420409942248">
        <wsse:Username>528725.RTCMACERT</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">tGupsbJwWtnQU1usa9hBFYWfnRk=</wsse:Password>
        <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">utFyPzosQNlMFihkXMCZuw==</wsse:Nonce>
        <wsu:Created>2018-11-12T16:43:14.224Z</wsu:Created>
      </wsse:UsernameToken>
      <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="X509-0EDE7F54075E85BDF615420409941614">MIIGIDCCBQigAwIBAgIQ ... OQl+57Pa5lM1Mj</wsse:BinarySecurityToken>
      <ds:Signature Id="SIG-0EDE7F54075E85BDF615420409941897" 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="cmaw soap xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
          <ds:Reference URI="#TS-0EDE7F54075E85BDF615420409941283">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="wsse cmaw soap xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>fM/i6lk0onD4vDQtHrKKrv8JeT6IgqFwV3FBBeymS28=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>e9+LmcpbcgZ+m282+57rIJjsU8oWjkrQrql5u9qmPxTkDjjjqOq0O8OOj+Ud3/L0p8w8bg07ByPK7RwfDCiZOZMvuqLup4wR+l7IKm ... LCakMIqQpuESXw==</ds:SignatureValue>
        <ds:KeyInfo Id="KI-0EDE7F54075E85BDF615420409941825">
          <wsse:SecurityTokenReference wsu:Id="STR-0EDE7F54075E85BDF615420409941836">
            <wsse:Reference URI="#X509-0EDE7F54075E85BDF615420409941614" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      <wsu:Timestamp wsu:Id="TS-0EDE7F54075E85BDF615420409941283">
        <wsu:Created>2018-11-12T16:43:14Z</wsu:Created>
        <wsu:Expires>2018-11-12T16:43:44Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <xsd:cardInqMaintDisplayParam>
      <cmaw:cardNumber>5287250200316234</cmaw:cardNumber>
      <cmaw:memberNumber>0</cmaw:memberNumber>
      <cmaw:endUser>RTCMA</cmaw:endUser>
    </xsd:cardInqMaintDisplayParam>
  </soap:Body>
</soap:Envelope>

SOAP-сообщение, сгенерированное кодом:

<soap:Envelope xmlns:cmaw="http://estarstation.com/cmaWS/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://estarstation.com/xsd">
  <soap:Header>
    <wsse:Security soap:mustUnderstand="1" 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:UsernameToken wsu:Id="UsernameToken-0EDE7F54075E85BDF615420409942248">
        <wsse:Username>528725.RTCMACERT</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">tGupsbJwWtnQU1usa9hBFYWfnRk=</wsse:Password>
        <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">utFyPzosQNlMFihkXMCZuw==</wsse:Nonce>
        <wsu:Created>2018-11-12T16:43:14.224Z</wsu:Created>
      </wsse:UsernameToken>
      <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="X509-0EDE7F54075E85BDF615420409941614">MIIGIDCCBQigAwIBAgIQ ... OQl+57Pa5lM1Mj</wsse:BinarySecurityToken>
      <ds:Signature Id="SIG-0EDE7F54075E85BDF615420409941897" 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="cmaw soap xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
          </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
          <ds:Reference URI="#TS-0EDE7F54075E85BDF615420409941283">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                <ec:InclusiveNamespaces PrefixList="wsse cmaw soap xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>fM/i6lk0onD4vDQtHrKKrv8JeT6IgqFwV3FBBeymS28=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>AvZBW8ejFNfnDFuWzAoNFBwXYjrQ2NVW/Ldj17E5D8XydWLskZTROMvaaSgcu72cgEgHUrC8mlhePduzvrjzP3Fuf18oRMaLhqGs85 ... eOegQ8EZHEp1ZQ==</ds:SignatureValue>
        <ds:KeyInfo Id="KI-0EDE7F54075E85BDF615420409941825">
          <wsse:SecurityTokenReference wsu:Id="STR-0EDE7F54075E85BDF615420409941836">
            <wsse:Reference URI="#X509-0EDE7F54075E85BDF615420409941614" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      <wsu:Timestamp wsu:Id="TS-0EDE7F54075E85BDF615420409941283">
        <wsu:Created>2018-11-12T16:43:14Z</wsu:Created>
        <wsu:Expires>2018-11-12T16:43:44Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <xsd:cardInqMaintDisplayParam>
      <cmaw:cardNumber>5287250200316234</cmaw:cardNumber>
      <cmaw:memberNumber>0</cmaw:memberNumber>
      <cmaw:endUser>RTCMA</cmaw:endUser>
    </xsd:cardInqMaintDisplayParam>
  </soap:Body>
</soap:Envelope>

Хотя я могу сгенерировать совпадение DigestValue в подписи, я не могу сопоставить SignatureValue. И программа SOAPUI, и программа .NET используют один и тот же клиентский сертификат X509.

Фрагмент кода, использованный для создания элемента Signature в заголовке SOAP.

  X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(Settings.Default.CertFilePFX), Settings.Default.CertPassword, X509KeyStorageFlags.Exportable);

  XmlDsigDocument xmlHeader = new XmlDsigDocument();      // Create a new XML document.

  xmlHeader.Load ( new XmlTextReader ( FileName ) );      // Load the passed XML file using its name.

  XmlNamespaceManager nSpMgr = new XmlNamespaceManager(xmlHeader.NameTable);
  nSpMgr.AddNamespace ( "soap", CustomSignedXml.xmlSoapEnvelopeUrl );
  nSpMgr.AddNamespace ( "wsu", CustomSignedXml.xmlOasisWSSSecurityUtilUrl );
  nSpMgr.AddNamespace ( "wsse", CustomSignedXml.xmlOasisWSSSecurityExtUrl );
  nSpMgr.AddNamespace ( "ec", CustomSignedXml.xmlOasisWSSSecurityExtUrl );

  XPathNavigator docNav = xmlHeader.CreateNavigator();
  XPathNavigator timestampNav = docNav.SelectSingleNode("/soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp", nSpMgr);
  XPathNavigator binarysecuritytokenNav = docNav.SelectSingleNode("/soap:Envelope/soap:Header/wsse:Security/wsse:BinarySecurityToken", nSpMgr);

  string timestampID = timestampNav.GetAttribute ( "Id", CustomSignedXml.xmlOasisWSSSecurityUtilUrl );
  string binarySecurityTokenID = binarysecuritytokenNav.GetAttribute ( "Id", CustomSignedXml.xmlOasisWSSSecurityUtilUrl );

  RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(new CspParameters(24));
  rsaKey.PersistKeyInCsp = false;

  string exportedKeyMaterial = cert.PrivateKey.ToXmlString(true);
  rsaKey.FromXmlString ( exportedKeyMaterial );

  CustomSignedXml signedXml = new CustomSignedXml(xmlHeader);
  signedXml.SigningKey = rsaKey;
  signedXml.Signature.Id = "SIG-0EDE7F54075E85BDF615420409941897";
  signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
  signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

  XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
  canMethod.InclusiveNamespacesPrefixList = "cmaw soap xsd";

  Reference reference = new Reference();
  reference.Uri = "#" + timestampID;
  reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";

  XmlDsigExcC14NTransform transformDataTS = new XmlDsigExcC14NTransform();
  transformDataTS.InclusiveNamespacesPrefixList = "wsse cmaw soap xsd";

  byte[] dataToHashTS = Encoding.UTF8.GetBytes(timestampNav.OuterXml);
  transformDataTS.LoadInput ( new MemoryStream ( dataToHashTS ) );

  reference.AddTransform ( transformDataTS );

  signedXml.AddReference ( reference );

  KeyInfo keyInfo = new KeyInfo();
  keyInfo.Id = "KI-0EDE7F54075E85BDF615420409941825";

  SecurityTokenReference skr = new SecurityTokenReference();
  skr.Id = "STR-0EDE7F54075E85BDF615420409941836";
  skr.Reference = binarySecurityTokenID;   // Binary Security Token ID  
  skr.ValueType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";

  keyInfo.AddClause ( skr );
  signedXml.KeyInfo = keyInfo;

  signedXml.ComputeSignature ( );       // Compute the signature

  XmlElement xmlDigitalSignature = signedXml.GetXml();

Настройки SOAPUI WSS

Как видите, подпись генерируется с использованием этих свойств:

Алгоритм подписи: rsa-sha256 Подпись Каноникализация: xml-exc-c14n # Алгоритм дайджеста: xmlenc # sha256

Или кто-то знает, как генерировать SignatureValue с учетом DigestValue? Если да, используете ли вы Base64 DigitalValue или конвертируете Base64 DigestValue в байтовый массив для расчета SignatureValue.

Буду признателен за любые рекомендации, потому что я работаю над этим в течение нескольких недель, чтобы получить правильное значение SignatureValue.

...