Objective-C
Objective-C
Sign with BinarySecurityToken
See more XML Digital Signatures Examples
Demonstrates creating an XML signature using a BinarySecurityToken.Chilkat Objective-C Downloads
#import <CkoCert.h>
#import <CkoXml.h>
#import <CkoDateTime.h>
#import <CkoBinData.h>
#import <CkoXmlDSigGen.h>
#import <CkoStringBuilder.h>
BOOL success = NO;
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// -------------------------------------------------------------------------
// Load a cert + private key from a PFX.
CkoCert *cert = [[CkoCert alloc] init];
success = [cert LoadPfxFile: @"qa_data/pfx/cert_test123.pfx" password: @"test123"];
if (success != YES) {
NSLog(@"%@",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.
//
CkoXml *xml = [[CkoXml alloc] init];
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 UpdateAttrAt: @"S:Header|To" autoCreate: YES attrName: @"xmlns" attrValue: @"http://www.w3.org/2005/08/addressing"];
[xml UpdateAttrAt: @"S:Header|To" autoCreate: YES attrName: @"wsu:Id" attrValue: @"_5002"];
[xml UpdateChildContent: @"S:Header|To" value: @"https://XXXXXXXXX"];
[xml UpdateAttrAt: @"S:Header|Action" autoCreate: YES attrName: @"xmlns" attrValue: @"http://www.w3.org/2005/08/addressing"];
[xml UpdateAttrAt: @"S:Header|Action" autoCreate: YES attrName: @"xmlns:S" attrValue: @"http://www.w3.org/2003/05/soap-envelope"];
[xml UpdateAttrAt: @"S:Header|Action" autoCreate: YES attrName: @"S:mustUnderstand" attrValue: @"true"];
[xml UpdateChildContent: @"S:Header|Action" value: @"http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"];
[xml UpdateAttrAt: @"S:Header|ReplyTo" autoCreate: YES 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 UpdateAttrAt: @"S:Header|FaultTo" autoCreate: YES 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 UpdateAttrAt: @"S:Header|MessageID" autoCreate: YES attrName: @"xmlns" attrValue: @"http://www.w3.org/2005/08/addressing"];
[xml UpdateChildContent: @"S:Header|MessageID" value: @"uuid:e9033251-4ff0-4618-8baf-4952ab5fd207"];
[xml UpdateAttrAt: @"S:Header|wsse:Security" autoCreate: YES attrName: @"S:mustUnderstand" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsu:Timestamp" autoCreate: YES attrName: @"xmlns:ns17" attrValue: @"http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsu:Timestamp" autoCreate: YES attrName: @"xmlns:ns16" attrValue: @"http://schemas.xmlsoap.org/soap/envelope/"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsu:Timestamp" autoCreate: YES attrName: @"wsu:Id" attrValue: @"_1"];
// Get the current date/time in timestamp format, such as "2018-05-23T02:38:27Z"
CkoDateTime *dt = [[CkoDateTime alloc] init];
[dt SetFromCurrentSystemTime];
[xml UpdateChildContent: @"S:Header|wsse:Security|wsu:Timestamp|wsu:Created" value: [dt GetAsTimestamp: NO]];
// Add 5 minutes.
[dt AddSeconds: [NSNumber numberWithInt: 300]];
[xml UpdateChildContent: @"S:Header|wsse:Security|wsu:Timestamp|wsu:Expires" value: [dt GetAsTimestamp: NO]];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsse:BinarySecurityToken" autoCreate: YES attrName: @"xmlns:ns17" attrValue: @"http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsse:BinarySecurityToken" autoCreate: YES attrName: @"xmlns:ns16" attrValue: @"http://schemas.xmlsoap.org/soap/envelope/"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsse:BinarySecurityToken" autoCreate: YES attrName: @"ValueType" attrValue: @"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsse:BinarySecurityToken" autoCreate: YES attrName: @"EncodingType" attrValue: @"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"];
[xml UpdateAttrAt: @"S:Header|wsse:Security|wsse:BinarySecurityToken" autoCreate: YES attrName: @"wsu:Id" attrValue: @"uuid_43470044-78b4-4b23-926a-b7f590d24cb8"];
CkoBinData *bdCert = [[CkoBinData alloc] init];
[cert ExportCertDerBd: bdCert];
// Get the cert as base64 on one line.
[xml UpdateChildContent: @"S:Header|wsse:Security|wsse:BinarySecurityToken" value: [bdCert GetEncoded: @"base64"]];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken" autoCreate: YES 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 UpdateAttrAt: @"S:Body|RequestSecurityToken|wsp:AppliesTo" autoCreate: YES attrName: @"xmlns:wsp" attrValue: @"http://schemas.xmlsoap.org/ws/2004/09/policy"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|wsp:AppliesTo|EndpointReference:EndpointReference" autoCreate: YES attrName: @"xmlns:EndpointReference" attrValue: @"http://www.w3.org/2005/08/addressing"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|wsp:AppliesTo|EndpointReference:EndpointReference" autoCreate: YES 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 UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims" autoCreate: YES attrName: @"xmlns:i" attrValue: @"http://schemas.xmlsoap.org/ws/2005/05/identity"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims" autoCreate: YES attrName: @"Dialect" attrValue: @"http://schemas.xmlsoap.org/ws/2005/05/identity"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType" autoCreate: YES attrName: @"Optional" attrValue: @"false"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/abn"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[1]" autoCreate: YES attrName: @"Optional" attrValue: @"false"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[1]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/commonname"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[2]" autoCreate: YES attrName: @"Optional" attrValue: @"false"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[2]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/credentialtype"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[3]" autoCreate: YES attrName: @"Optional" attrValue: @"false"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[3]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/samlsubjectid"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[4]" autoCreate: YES attrName: @"Optional" attrValue: @"false"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[4]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/fingerprint"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[5]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[5]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/sbr_personid"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[6]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[6]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/givennames"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[7]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[7]" autoCreate: YES attrName: @"Uri" attrValue: @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[8]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[8]" autoCreate: YES attrName: @"Uri" attrValue: @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[9]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[9]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/credentialadministrator"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[10]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[10]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/stalecrlminutes"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[11]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[11]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/subjectdn"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[12]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[12]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/issuerdn"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[13]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[13]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/notafterdate"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[14]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[14]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/certificateserialnumber"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[15]" autoCreate: YES attrName: @"Optional" attrValue: @"true"];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Claims|i:ClaimType[15]" autoCreate: YES attrName: @"Uri" attrValue: @"http://XXXXXXXXX/2008/06/identity/claims/previoussubject"];
[dt SetFromCurrentSystemTime];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Lifetime|wsu:Created" autoCreate: YES 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: NO]];
// Add 40 minutes.
[dt AddSeconds: [NSNumber numberWithInt: 2400]];
[xml UpdateAttrAt: @"S:Body|RequestSecurityToken|Lifetime|wsu:Expires" autoCreate: YES 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: NO]];
[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>
CkoXml *keyInfoXml = [[CkoXml alloc] init];
keyInfoXml.Tag = @"wsse:SecurityTokenReference";
[keyInfoXml UpdateAttrAt: @"wsse:Reference" autoCreate: YES attrName: @"URI" attrValue: @"#uuid_43470044-78b4-4b23-926a-b7f590d24cb8"];
[keyInfoXml UpdateAttrAt: @"wsse:Reference" autoCreate: YES 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.
//
CkoXmlDSigGen *gen = [[CkoXmlDSigGen alloc] init];
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 = NO;
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: YES];
// Indicated we want an indented signature for easier human reading.
gen.Behaviors = @"IndentedSignature";
// Sign the XML..
CkoStringBuilder *sbXml = [[CkoStringBuilder alloc] init];
[xml GetXmlSb: sbXml];
success = [gen CreateXmlDSigSb: sbXml];
if (success != YES) {
NSLog(@"%@",gen.LastErrorText);
return;
}
// Examine the signed XML
NSLog(@"%@",[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>
//