Swift
Swift
Sign XML (XAdES) using USB Token or Smartcard on iOS iPhone
Demonstrates how to sign XML using an HSM (USB token or smart card) connected to an iPhone.Note: This example requires Chilkat v10.0.0 or greater.
Chilkat Swift Downloads
func chilkatTest() {
var success: Bool = false
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// When signing with a USB token or smartcard, the only coding difference is how the certificate
// gets loaded. To load the default certificate from the connected USB token or smartcard, just call
// LoadFromSmartcard with an empty string argument.
//
// This requires Chilkat v10.0.0 or later.
//
// ------------------------------------------------------------------------------------------------------------------------------------------------------
// Important: In your Xcode project, you'll need to add the "com.apple.token" entitlement.
// Also, adding the com.apple.token in the "Project > Signing & Capabilities" will actually add $(AppIdentifierPrefix)com.apple.token, which does not work.
// Edit the entitlements file directly and add only com.apple.token
// If using a Yubikey, you'll only find the certificate if it is added in the Yubikey app as Public.
// ------------------------------------------------------------------------------------------------------------------------------------------------------
let cert = CkoCert()!
success = cert.load(fromSmartcard: "")
if success == false {
print("\(cert.lastErrorText!)")
return
}
// Create the XML to be signed.
let sbXml = CkoStringBuilder()!
var bCrlf: Bool = true
sbXml.appendLine(str: "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>", crlf: bCrlf)
sbXml.appendLine(str: "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">", crlf: bCrlf)
sbXml.appendLine(str: " <SOAP-ENV:Header>", crlf: bCrlf)
sbXml.appendLine(str: " <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" SOAP-ENV:mustUnderstand=\"1\"></wsse:Security>", crlf: bCrlf)
sbXml.appendLine(str: " </SOAP-ENV:Header>", crlf: bCrlf)
sbXml.appendLine(str: " <SOAP-ENV:Body xmlns:SOAP-SEC=\"http://schemas.xmlsoap.org/soap/security/2000-12\" SOAP-SEC:id=\"Body\">", crlf: bCrlf)
sbXml.appendLine(str: " <z:FooBar xmlns:z=\"http://example.com\" />", crlf: bCrlf)
sbXml.appendLine(str: " </SOAP-ENV:Body>", crlf: bCrlf)
sbXml.appendLine(str: "</SOAP-ENV:Envelope>", crlf: bCrlf)
// Prepare for signing...
let gen = CkoXmlDSigGen()!
// Indicate where the Signature will be inserted.
gen.sigLocation = "SOAP-ENV:Envelope|SOAP-ENV:Header|wsse:Security"
// Add a reference to the fragment of the XML to be signed.
// Note: "Body" refers to the XML element having an "id" equal to "Body", where "id" is case insensitive
// and where any namespace might qualify the attribute. In this case, the SOAP-ENV:Body fragment is signed
// NOT because the tag = "Body", but because it has SOAP-SEC:id="Body"
gen.addSameDocRef(id: "Body", digestMethod: "sha1", canonMethod: "EXCL_C14N", prefixList: "", refType: "")
// (You can read about the SignedInfoPrefixList in the online reference documentation. It's optional..)
gen.signedInfoPrefixList = "wsse SOAP-ENV"
gen.keyInfoType = "X509Data"
gen.x509Type = "IssuerSerial"
var bUsePrivateKey: Bool = true
success = gen.setX509Cert(cert: cert, usePrivateKey: bUsePrivateKey)
if success != true {
print("\(gen.lastErrorText!)")
cert = nil
return
}
// Everything's specified. Now create and insert the Signature
success = gen.createXmlDSigSb(sbXml: sbXml)
if success != true {
print("\(gen.lastErrorText!)")
return
}
// Examine the XML with the digital signature inserted
print("\(sbXml.getAsString()!)")
}