Python sign SOAP request using BinarySecurityToken Python sign SOAP request using BinarySecurityToken python python

Python sign SOAP request using BinarySecurityToken


Chicklat with its API provides two examples (see at bottom) for solving this problem. The first signs a certificate using SecurityTokenReference and the second signs a certificate using BinaryTokenReference. You don't have to rely on this API as it's subjected to license costs, you can do it but you can use alternative libraries to do this (below in the post I posted alternatives). Those examples are good starting points to get to your expected results by understanding the way Chicklat API does it and using your custom methods.

In the first example:

  • (#1) A SOAP XML template is loaded, this is the template that will be signed with the pfx certificate and the BinarySecurityToken;
  • (#2-3) The pfx, a single file containing the password protected certificate along with its private key, is loaded, then its private key and its internal certificate are extracted by providing a password as input, which is the password used when the certificate was issued;
  • (#4) Once the certificate is extracted from the pfx file, it is BASE64-encoded. Inside the XML template, BASE64_CERT is replaced by this string as a value provided to wsse:BinarySecurityToken;
  • (#5) Build the wsse:SecurityTokenReference XML. This XML is a KeyInfo, a storage to contain your certificate private key, used to verify the signature;
  • (#6) Signing the XML using Chicklat XML Digital Signature Generator.

You can adapt the first example by using the second example. This can be done by following these changes:

  • Change the way the sbXml is constructed. Example 2, starting from chilkat.CkXml(), shows a way to do it and setup parameters. The output XML structure would be similar to this schema to use BinarySecurityToken:
<?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:exc14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">   <S:Header>      <To xmlns="http://www.w3.org/2005/08/addressing" wsu:Id="_5002">https://XXXXXXXXX</To>      <Action xmlns="http://www.w3.org/2005/08/addressing" S:mustUnderstand="true">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</Action>      <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">         <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>      </ReplyTo>      <FaultTo xmlns="http://www.w3.org/2005/08/addressing">         <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>      </FaultTo>      <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:e9033251-4ff0-4618-8baf-4952ab5fd207</MessageID>      <wsse:Security S:mustUnderstand="true">         <wsu:Timestamp xmlns:ns16="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns17="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" wsu:Id="_1">            <wsu:Created>2018-05-23T02:38:27Z</wsu:Created>            <wsu:Expires>2018-05-23T02:43:27Z</wsu:Expires>         </wsu:Timestamp>         <wsse:BinarySecurityToken xmlns:ns16="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns17="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" wsu:Id="uuid_43470044-78b4-4b23-926a-b7f590d24cb8">MIIEIjCCAwqgAwIBAgIDAmCRMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYDVQQGEwJBVTElMCMGA1UEChMcQXVzdHJhbGlhbiBCdXNpbmVzcyBSZWdpc3RlcjEgMB4GA1UECxMXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLTArBgNVBAMTJFRlc3QgQXVzdHJhbGlhbiBCdXNpbmVzcyBSZWdpc3RlciBDQTAeFw0xNzAzMDEwMzQyMTBaFw0xOTAzMDEwMzQyMTBaMFYxETAPBgNVBC4TCDIwMDgwMTYxMQswCQYDVQQGEwJBVTEUMBIGA1UEChMLOTYwODU1MjE2MDYxHjAcBgNVBAMTFUNPUlAgVEFYQVRJT04gTUFOQUdFUjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs6zlEhQOOpPPXffUPgpmbPl6qtQ3QaYgYvSTGLOL2pxuwGlZc5oW93zTwh5yq0r5NAgouGx9Oo6pYBO/xEUst5g3VW5BmbuOyGk3UvKVLHTnWlt8KCaRwW/qOyya8ZYfJm8+OQHtmMZc0pjj/Pcn8lrN61BKyjAYwK3CTKa60gcCAwEAAaOCAUswggFHMAwGA1UdEwEB/wQCMAAwgewGA1UdIASB5DCB4TCB3gYJKiQBlzllAQcBMIHQMIGuBggrBgEFBQcCAjCBoRqBnlRoaXMgY2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgdXNlZCBmb3IgdGhlIHB1cnBvc2UgcGVybWl0dGVkIGluIHRoZSBhcHBsaWNhYmxlIENlcnRpZmljYXRlIFBvbGljeS4gTGltaXRlZCBsaWFiaWxpdHkgYXBwbGllcyAtIHJlZmVyIHRvIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kuMB0GCCsGAQUFBwIBFhF3d3cudGVzdGFicmNhLmNvbTAXBgYqJAGCTQEEDRYLOTYwODU1MjE2MDYwDgYDVR0PAQH/BAQDAgTwMB8GA1UdIwQYMBaAFI0lJ7xfoJpx55N3+bAZYiyZdlr9MA0GCSqGSIb3DQEBCwUAA4IBAQBQoYVRGRf3QIkxFa4ecI2Kxph5vrUuTdzIaDm+mCnHyaamnAbBH7WCPymuK+ZFQo1lWcyMzQpf7N/6/e0sZH3OD0JIuBF3AKQbvwVLfJ5x/Xu2Cz9ZAkkonL0wIXXAmGIPNjZD1WwzPUYbUuZw+GqOIeSOYitIuz7N3y6vKIgLLzghVAcXBPPuMqqcL/PwSIQ9LRTqa4zhNy2Bn+CwR9QanS6jGTXfpOmetsbRckE+WgCwzMz5iqgTrP8AYwsDYxFBdmktrO+u1V0PrESeZFTbToRs2UUtEaYowIDEb/6KqKJxs7AZN+Nt5r1RaOfbsr6KJDOS5K+VRRtjAGwcXBXN</wsse:BinarySecurityToken>      </wsse:Security>   </S:Header>   <S:Body>      <RequestSecurityToken xmlns="http://docs.oasis-open.org/ws-sx/ws-trust/200512">         <RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</RequestType>         <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">            <EndpointReference:EndpointReference xmlns:EndpointReference="http://www.w3.org/2005/08/addressing" xmlns="http://www.w3.org/2005/08/addressing">               <Address>https://XXXXXXXXX/services</Address>            </EndpointReference:EndpointReference>         </wsp:AppliesTo>         <TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</TokenType>         <Claims xmlns:i="http://schemas.xmlsoap.org/ws/2005/05/identity" Dialect="http://schemas.xmlsoap.org/ws/2005/05/identity">            <i:ClaimType Optional="false" Uri="http://XXXXXXXXX/2008/06/identity/claims/abn" />            <i:ClaimType Optional="false" Uri="http://XXXXXXXXX/2008/06/identity/claims/commonname" />            <i:ClaimType Optional="false" Uri="http://XXXXXXXXX/2008/06/identity/claims/credentialtype" />            <i:ClaimType Optional="false" Uri="http://XXXXXXXXX/2008/06/identity/claims/samlsubjectid" />            <i:ClaimType Optional="false" Uri="http://XXXXXXXXX/2008/06/identity/claims/fingerprint" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/sbr_personid" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/givennames" />            <i:ClaimType Optional="true" Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" />            <i:ClaimType Optional="true" Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/credentialadministrator" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/stalecrlminutes" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/subjectdn" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/issuerdn" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/notafterdate" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/certificateserialnumber" />            <i:ClaimType Optional="true" Uri="http://XXXXXXXXX/2008/06/identity/claims/previoussubject" />         </Claims>         <Lifetime>            <wsu:Created>2018-05-23T02:38:27.906Z</wsu:Created>            <wsu:Expires>2018-05-23T03:08:27.906Z</wsu:Expires>         </Lifetime>         <KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</KeyType>         <KeySize>512</KeySize>      </RequestSecurityToken>   </S:Body></S:Envelope>
  • You can use OpenSSL.crypto to manage the pfx file extracting the private key and the certificate;

  • You can use SignXML for the XML Digital Signature generation.

from lxml import etreefrom signxml import XMLSigner, XMLVerifierdata_to_sign = "<Test/>" // Your XMLroot = etree.fromstring(data_to_sign)signed_root = XMLSigner().sign(root, key=PRIVATE_KEY, cert=CERTIFICATE)verified_data = XMLVerifier().verify(signed_root).signed_xml

Reference examples:

Example 1: Sign SOAP XML using a wsse:SecurityTokenReference

Example 2: Sign with BinarySecurityToken