Sample code for 30+ languages & platforms
Visual FoxPro

PKCS11 XML Signature using Certificate and Private Key on Smart Card / USB Token

See more PKCS11 Examples

Sample code showing how to use PKCS11 to create an XML digital signature with a certificate and private key stored on a smart card or USB token.

Note: This example requires Chilkat v9.5.0.96 or later.

Chilkat Visual FoxPro Downloads

Visual FoxPro
LOCAL lnSuccess
LOCAL loPkcs11
LOCAL lnUserType
LOCAL lcPin
LOCAL loCert
LOCAL loXml
LOCAL loGen
LOCAL lnBUsePrivateKey
LOCAL loSbXml

lnSuccess = 0

* This example requires the Chilkat API to have been previously unlocked.
* See Global Unlock Sample for sample code.

* Note: Chilkat's PKCS11 implementation runs on Windows, Linux, Mac OS X, and other supported operating systems.

loPkcs11 = CreateObject('Chilkat.Pkcs11')

* This example is tested on Windows using a Giesecke and Devrient Sm@rtCafe Expert 3.2 smart card.
* You will use the DLL (or shared lib) provided by your smart card vendor, or a DLL compatible with your smart card.
* On Windows, if the DLL is located in C:\Windows\System32, specify only the filename.
* Otherwise provide the full path.
loPkcs11.SharedLibPath = "aetpkss1.dll"

* Make it an authenticated session by calling Login.
lnUserType = 1
* Make sure to use the correct PIN for your smart card..
lcPin = "0000"

lnSuccess = loPkcs11.QuickSession(lnUserType,lcPin)
IF (lnSuccess = 0) THEN
    ? loPkcs11.LastErrorText
    RELEASE loPkcs11
    CANCEL
ENDIF

* Get the certificate (on the smart card) that has a private key.
loCert = CreateObject('Chilkat.Cert')
lnSuccess = loPkcs11.FindCert("privateKey","",loCert)
IF (lnSuccess = 1) THEN
    ? "Cert with private key: " + loCert.SubjectCN
ELSE
    ? "No certificates having a private key were found."
    lnSuccess = loPkcs11.CloseSession()
    RELEASE loPkcs11
    RELEASE loCert
    CANCEL
ENDIF

* --------------------------------------------------------------------------
* At this point, we have the cert to be used for signing.
* Our XML signing code is the same as for a cert obtained from any other source..

* First generate the following XML to be signed:
* Use this online tool to generate code from sample XML: 
* Generate Code to Create XML

* <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
* <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
*     <SOAP-ENV:Header>
*         <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>
*     </SOAP-ENV:Header>
*     <SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body">
*         <z:FooBar xmlns:z="http://example.com" />
*     </SOAP-ENV:Body>
* </SOAP-ENV:Envelope>

loXml = CreateObject('Chilkat.Xml')
loXml.Tag = "SOAP-ENV:Envelope"
loXml.AddAttribute("xmlns:SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/")
loXml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",1,"xmlns:wsse","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
loXml.UpdateAttrAt("SOAP-ENV:Header|wsse:Security",1,"SOAP-ENV:mustUnderstand","1")
loXml.UpdateAttrAt("SOAP-ENV:Body",1,"xmlns:SOAP-SEC","http://schemas.xmlsoap.org/soap/security/2000-12")
loXml.UpdateAttrAt("SOAP-ENV:Body",1,"SOAP-SEC:id","Body")
loXml.UpdateAttrAt("SOAP-ENV:Body|z:FooBar",1,"xmlns:z","http://example.com")

loGen = CreateObject('Chilkat.XmlDSigGen')

* Indicate where the Signature will be inserted.
loGen.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"
loGen.AddSameDocRef("Body","sha1","EXCL_C14N","","")

* (You can read about the SignedInfoPrefixList in the online reference documentation.  It's optional..)
loGen.SignedInfoPrefixList = "wsse SOAP-ENV"

* Provide the private key for signing via the certificate, and indicate that
* we want the base64 of the certificate embedded in the KeyInfo.
loGen.KeyInfoType = "X509Data"
loGen.X509Type = "Certificate"

lnBUsePrivateKey = 1
lnSuccess = loGen.SetX509Cert(loCert,lnBUsePrivateKey)
IF (lnSuccess <> 1) THEN
    ? loGen.LastErrorText
    lnSuccess = loPkcs11.CloseSession()
    RELEASE loPkcs11
    RELEASE loCert
    RELEASE loXml
    RELEASE loGen
    CANCEL
ENDIF

* Everything's specified.  Now create and insert the Signature
loSbXml = CreateObject('Chilkat.StringBuilder')
loXml.EmitCompact = 1
loXml.GetXmlSb(loSbXml)

lnSuccess = loGen.CreateXmlDSigSb(loSbXml)
IF (lnSuccess <> 1) THEN
    ? loGen.LastErrorText
    lnSuccess = loPkcs11.CloseSession()
    RELEASE loPkcs11
    RELEASE loCert
    RELEASE loXml
    RELEASE loGen
    RELEASE loSbXml
    CANCEL
ENDIF

* Examine the XML with the digital signature inserted
? loSbXml.GetAsString()

* --------------------------------------------------------------------------

* Revert to an unauthenticated session by calling Logout.
lnSuccess = loPkcs11.Logout()
IF (lnSuccess = 0) THEN
    ? loPkcs11.LastErrorText
    lnSuccess = loPkcs11.CloseSession()
    RELEASE loPkcs11
    RELEASE loCert
    RELEASE loXml
    RELEASE loGen
    RELEASE loSbXml
    CANCEL
ENDIF

* When finished, close the session.
* It is important to close the session (memory leaks will occur if the session is not properly closed).
lnSuccess = loPkcs11.CloseSession()
IF (lnSuccess = 0) THEN
    ? loPkcs11.LastErrorText
    RELEASE loPkcs11
    RELEASE loCert
    RELEASE loXml
    RELEASE loGen
    RELEASE loSbXml
    CANCEL
ENDIF

? "Success."

RELEASE loPkcs11
RELEASE loCert
RELEASE loXml
RELEASE loGen
RELEASE loSbXml