Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(Swift 3,4,5...) Sign with BinarySecurityTokenDemonstrates creating an XML signature using a BinarySecurityToken.
func chilkatTest() { // This example requires the Chilkat API to have been previously unlocked. // See Global Unlock Sample for sample code. var success: Bool // ------------------------------------------------------------------------- // Load a cert + private key from a PFX. let cert = CkoCert()! success = cert.loadPfxFile("qa_data/pfx/cert_test123.pfx", password: "test123") if success != true { print("\(cert.lastErrorText!)") return } // ------------------------------------------------------------------------- // Create the XML that is to be signed. // // The XML we're creating can be found at Sample Pre-Signed XML with BinarySecurityToken // The online tool at http://tools.chilkat.io/xmlCreate.cshtml can be used to generate the following XML creation code. // let xml = CkoXml()! xml.tag = "S:Envelope" xml.addAttribute("xmlns:S", value: "http://www.w3.org/2003/05/soap-envelope") xml.addAttribute("xmlns:wsse11", value: "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd") xml.addAttribute("xmlns:wsse", value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd") xml.addAttribute("xmlns:wsu", value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") xml.addAttribute("xmlns:xs", value: "http://www.w3.org/2001/XMLSchema") xml.addAttribute("xmlns:ds", value: "http://www.w3.org/2000/09/xmldsig#") xml.addAttribute("xmlns:exc14n", value: "http://www.w3.org/2001/10/xml-exc-c14n#") xml.updateAttr(at: "S:Header|To", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateAttr(at: "S:Header|To", autoCreate: true, attrName: "wsu:Id", attrValue: "_5002") xml.updateChildContent("S:Header|To", value: "https://XXXXXXXXX") xml.updateAttr(at: "S:Header|Action", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateAttr(at: "S:Header|Action", autoCreate: true, attrName: "xmlns:S", attrValue: "http://www.w3.org/2003/05/soap-envelope") xml.updateAttr(at: "S:Header|Action", autoCreate: true, attrName: "S:mustUnderstand", attrValue: "true") xml.updateChildContent("S:Header|Action", value: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue") xml.updateAttr(at: "S:Header|ReplyTo", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateChildContent("S:Header|ReplyTo|Address", value: "http://www.w3.org/2005/08/addressing/anonymous") xml.updateAttr(at: "S:Header|FaultTo", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateChildContent("S:Header|FaultTo|Address", value: "http://www.w3.org/2005/08/addressing/anonymous") xml.updateAttr(at: "S:Header|MessageID", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateChildContent("S:Header|MessageID", value: "uuid:e9033251-4ff0-4618-8baf-4952ab5fd207") xml.updateAttr(at: "S:Header|wsse:Security", autoCreate: true, attrName: "S:mustUnderstand", attrValue: "true") xml.updateAttr(at: "S:Header|wsse:Security|wsu:Timestamp", autoCreate: true, attrName: "xmlns:ns17", attrValue: "http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512") xml.updateAttr(at: "S:Header|wsse:Security|wsu:Timestamp", autoCreate: true, attrName: "xmlns:ns16", attrValue: "http://schemas.xmlsoap.org/soap/envelope/") xml.updateAttr(at: "S:Header|wsse:Security|wsu:Timestamp", autoCreate: true, attrName: "wsu:Id", attrValue: "_1") // Get the current date/time in timestamp format, such as "2018-05-23T02:38:27Z" let dt = CkoDateTime()! dt.setFromCurrentSystemTime() xml.updateChildContent("S:Header|wsse:Security|wsu:Timestamp|wsu:Created", value: dt.getAsTimestamp(false)) // Add 5 minutes. dt.addSeconds(300) xml.updateChildContent("S:Header|wsse:Security|wsu:Timestamp|wsu:Expires", value: dt.getAsTimestamp(false)) xml.updateAttr(at: "S:Header|wsse:Security|wsse:BinarySecurityToken", autoCreate: true, attrName: "xmlns:ns17", attrValue: "http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512") xml.updateAttr(at: "S:Header|wsse:Security|wsse:BinarySecurityToken", autoCreate: true, attrName: "xmlns:ns16", attrValue: "http://schemas.xmlsoap.org/soap/envelope/") xml.updateAttr(at: "S:Header|wsse:Security|wsse:BinarySecurityToken", autoCreate: true, attrName: "ValueType", attrValue: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3") xml.updateAttr(at: "S:Header|wsse:Security|wsse:BinarySecurityToken", autoCreate: true, attrName: "EncodingType", attrValue: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary") xml.updateAttr(at: "S:Header|wsse:Security|wsse:BinarySecurityToken", autoCreate: true, attrName: "wsu:Id", attrValue: "uuid_43470044-78b4-4b23-926a-b7f590d24cb8") let bdCert = CkoBinData()! cert.exportDerBd(bdCert) // Get the cert as base64 on one line. xml.updateChildContent("S:Header|wsse:Security|wsse:BinarySecurityToken", value: bdCert.getEncoded("base64")) xml.updateAttr(at: "S:Body|RequestSecurityToken", autoCreate: true, attrName: "xmlns", attrValue: "http://docs.oasis-open.org/ws-sx/ws-trust/200512") xml.updateChildContent("S:Body|RequestSecurityToken|RequestType", value: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue") xml.updateAttr(at: "S:Body|RequestSecurityToken|wsp:AppliesTo", autoCreate: true, attrName: "xmlns:wsp", attrValue: "http://schemas.xmlsoap.org/ws/2004/09/policy") xml.updateAttr(at: "S:Body|RequestSecurityToken|wsp:AppliesTo|EndpointReference:EndpointReference", autoCreate: true, attrName: "xmlns:EndpointReference", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateAttr(at: "S:Body|RequestSecurityToken|wsp:AppliesTo|EndpointReference:EndpointReference", autoCreate: true, attrName: "xmlns", attrValue: "http://www.w3.org/2005/08/addressing") xml.updateChildContent("S:Body|RequestSecurityToken|wsp:AppliesTo|EndpointReference:EndpointReference|Address", value: "https://XXXXXXXXX/services") xml.updateChildContent("S:Body|RequestSecurityToken|TokenType", value: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims", autoCreate: true, attrName: "xmlns:i", attrValue: "http://schemas.xmlsoap.org/ws/2005/05/identity") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims", autoCreate: true, attrName: "Dialect", attrValue: "http://schemas.xmlsoap.org/ws/2005/05/identity") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType", autoCreate: true, attrName: "Optional", attrValue: "false") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/abn") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[1]", autoCreate: true, attrName: "Optional", attrValue: "false") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[1]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/commonname") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[2]", autoCreate: true, attrName: "Optional", attrValue: "false") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[2]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/credentialtype") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[3]", autoCreate: true, attrName: "Optional", attrValue: "false") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[3]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/samlsubjectid") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[4]", autoCreate: true, attrName: "Optional", attrValue: "false") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[4]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/fingerprint") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[5]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[5]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/sbr_personid") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[6]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[6]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/givennames") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[7]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[7]", autoCreate: true, attrName: "Uri", attrValue: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[8]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[8]", autoCreate: true, attrName: "Uri", attrValue: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[9]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[9]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/credentialadministrator") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[10]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[10]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/stalecrlminutes") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[11]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[11]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/subjectdn") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[12]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[12]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/issuerdn") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[13]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[13]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/notafterdate") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[14]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[14]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/certificateserialnumber") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[15]", autoCreate: true, attrName: "Optional", attrValue: "true") xml.updateAttr(at: "S:Body|RequestSecurityToken|Claims|i:ClaimType[15]", autoCreate: true, attrName: "Uri", attrValue: "http://XXXXXXXXX/2008/06/identity/claims/previoussubject") dt.setFromCurrentSystemTime() xml.updateAttr(at: "S:Body|RequestSecurityToken|Lifetime|wsu:Created", autoCreate: true, attrName: "xmlns:wsu", attrValue: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") xml.updateChildContent("S:Body|RequestSecurityToken|Lifetime|wsu:Created", value: dt.getAsTimestamp(false)) // Add 40 minutes. dt.addSeconds(2400) xml.updateAttr(at: "S:Body|RequestSecurityToken|Lifetime|wsu:Expires", autoCreate: true, attrName: "xmlns:wsu", attrValue: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") xml.updateChildContent("S:Body|RequestSecurityToken|Lifetime|wsu:Expires", value: dt.getAsTimestamp(false)) xml.updateChildContent("S:Body|RequestSecurityToken|KeyType", value: "http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey") xml.updateChildContent("S:Body|RequestSecurityToken|KeySize", value: "512") // Examine the pre-signed XML // println xml.GetXml(); // Build the custom KeyInfo XML we'll use: // // <wsse:SecurityTokenReference> // <wsse:Reference URI="#uuid_43470044-78b4-4b23-926a-b7f590d24cb8" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" /></wsse:SecurityTokenReference> let keyInfoXml = CkoXml()! keyInfoXml.tag = "wsse:SecurityTokenReference" keyInfoXml.updateAttr(at: "wsse:Reference", autoCreate: true, attrName: "URI", attrValue: "#uuid_43470044-78b4-4b23-926a-b7f590d24cb8") keyInfoXml.updateAttr(at: "wsse:Reference", autoCreate: true, attrName: "ValueType", attrValue: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3") // ------------------------------------------------------------------------- // Setup the XML Digital Signature Generator and add the XML Signature. // let gen = CkoXmlDSigGen()! gen.sigLocation = "S:Envelope|S:Header|wsse:Security" gen.signedInfoPrefixList = "wsse S" gen.addSameDocRef("_1", digestMethod: "sha1", canonMethod: "EXCL_C14N", prefixList: "wsu wsse S", refType: "") gen.addSameDocRef("_5002", digestMethod: "sha1", canonMethod: "EXCL_C14N", prefixList: "S", refType: "") gen.keyInfoType = "Custom" keyInfoXml.emitXmlDecl = false gen.customKeyInfoXml = keyInfoXml.getXml() // Specify the cert for signing (which has a private key because it was loaded from a PFX) gen.setX509Cert(cert, usePrivateKey: true) // Indicated we want an indented signature for easier human reading. gen.behaviors = "IndentedSignature" // Sign the XML.. let sbXml = CkoStringBuilder()! xml.getSb(sbXml) success = gen.createXmlDSigSb(sbXml) if success != true { print("\(gen.lastErrorText!)") return } // Examine the signed XML print("\(sbXml.getAsString()!)") // The resulting signature (extracted from the surrounding XML) looks something like this: // <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 xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse S" /> // </ds:CanonicalizationMethod> // <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> // <ds:Reference URI="#_1"> // <ds:Transforms> // <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> // <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsu wsse S" /> // </ds:Transform> // </ds:Transforms> // <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> // <ds:DigestValue>VAJMC/L/BDvml7Qv5CBMePbKDE8=</ds:DigestValue> // </ds:Reference> // <ds:Reference URI="#_5002"> // <ds:Transforms> // <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> // <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="S" /> // </ds:Transform> // </ds:Transforms> // <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> // <ds:DigestValue>sW/QFsk6kGv1dzeu0H9Qc/2kvAQ=</ds:DigestValue> // </ds:Reference> // </ds:SignedInfo> // <ds:SignatureValue>....</ds:SignatureValue> // <ds:KeyInfo> // <wsse:SecurityTokenReference> // <wsse:Reference URI="#uuid_43470044-78b4-4b23-926a-b7f590d24cb8" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" /> // </wsse:SecurityTokenReference> // </ds:KeyInfo> // </ds:Signature> // } |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.