PureBasic
PureBasic
Create AuthNRequest with embedded signature (HTTP-POST binding)
See more XML Digital Signatures Examples
Demonstrates how to create a SAML AuthNRequest with embedded signature (HTTP-POST binding).Chilkat PureBasic Downloads
IncludeFile "CkCert.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkXmlDSigGen.pb"
IncludeFile "CkXmlDSig.pb"
IncludeFile "CkStringBuilder.pb"
Procedure ChilkatExample()
success.i = 0
; This example requires the Chilkat API to have been previously unlocked.
; See Global Unlock Sample for sample code.
; This example will sign the following SAML AuthNRequest:
; <samlp:AuthnRequest
; xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
; xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
; ID="pfx41d8ef22-e612-8c50-9960-1b16f15741b3"
; Version="2.0" ProviderName="SP test" IssueInstant="2014-07-16T23:52:45Z"
; Destination="http://idp.example.com/SSOService.php"
; ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
; AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs">
; <saml:Issuer>http://sp.example.com/demo1/metadata.php</saml:Issuer>
; <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
; <samlp:RequestedAuthnContext Comparison="exact">
; <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
; </samlp:RequestedAuthnContext>
; </samlp:AuthnRequest>
; First we build the XML to be signed.
;
; Use this online tool to generate the code from sample XML:
; Generate Code to Create XML
success = 1
xmlToSign.i = CkXml::ckCreate()
If xmlToSign.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::setCkTag(xmlToSign, "samlp:AuthnRequest")
CkXml::ckAddAttribute(xmlToSign,"xmlns:samlp","urn:oasis:names:tc:SAML:2.0:protocol")
CkXml::ckAddAttribute(xmlToSign,"xmlns:saml","urn:oasis:names:tc:SAML:2.0:assertion")
CkXml::ckAddAttribute(xmlToSign,"ID","pfx41d8ef22-e612-8c50-9960-1b16f15741b3")
CkXml::ckAddAttribute(xmlToSign,"Version","2.0")
CkXml::ckAddAttribute(xmlToSign,"ProviderName","SP test")
CkXml::ckAddAttribute(xmlToSign,"IssueInstant","2014-07-16T23:52:45Z")
CkXml::ckAddAttribute(xmlToSign,"Destination","http://idp.example.com/SSOService.php")
CkXml::ckAddAttribute(xmlToSign,"ProtocolBinding","urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")
CkXml::ckAddAttribute(xmlToSign,"AssertionConsumerServiceURL","http://sp.example.com/demo1/index.php?acs")
CkXml::ckUpdateChildContent(xmlToSign,"saml:Issuer","http://sp.example.com/demo1/metadata.php")
CkXml::ckUpdateAttrAt(xmlToSign,"samlp:NameIDPolicy",1,"Format","urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")
CkXml::ckUpdateAttrAt(xmlToSign,"samlp:NameIDPolicy",1,"AllowCreate","true")
CkXml::ckUpdateAttrAt(xmlToSign,"samlp:RequestedAuthnContext",1,"Comparison","exact")
CkXml::ckUpdateChildContent(xmlToSign,"samlp:RequestedAuthnContext|saml:AuthnContextClassRef","urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")
; Also see the online tool to generate the code from sample already-signed XML:
; Generate XML Signature Creation Code from an Already-Signed XML Sample
gen.i = CkXmlDSigGen::ckCreate()
If gen.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXmlDSigGen::setCkSigLocation(gen, "samlp:AuthnRequest")
CkXmlDSigGen::setCkSigNamespacePrefix(gen, "ds")
CkXmlDSigGen::setCkSigNamespaceUri(gen, "http://www.w3.org/2000/09/xmldsig#")
CkXmlDSigGen::setCkSignedInfoCanonAlg(gen, "EXCL_C14N")
CkXmlDSigGen::setCkSignedInfoDigestMethod(gen, "sha1")
; -------- Reference 1 --------
CkXmlDSigGen::ckAddSameDocRef(gen,"pfx41d8ef22-e612-8c50-9960-1b16f15741b3","sha1","EXCL_C14N","","")
; Provide a certificate + private key. (PFX password is test123)
cert.i = CkCert::ckCreate()
If cert.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkCert::ckLoadPfxFile(cert,"qa_data/pfx/cert_test123.pfx","test123")
If success <> 1
Debug CkCert::ckLastErrorText(cert)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkCert::ckDispose(cert)
ProcedureReturn
EndIf
CkXmlDSigGen::ckSetX509Cert(gen,cert,1)
CkXmlDSigGen::setCkKeyInfoType(gen, "X509Data")
CkXmlDSigGen::setCkX509Type(gen, "Certificate")
; Load XML to be signed...
sbXml.i = CkStringBuilder::ckCreate()
If sbXml.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkXml::ckGetXmlSb(xmlToSign,sbXml)
CkXmlDSigGen::setCkBehaviors(gen, "IndentedSignature,ForceAddEnvelopedSignatureTransform")
; Sign the XML...
success = CkXmlDSigGen::ckCreateXmlDSigSb(gen,sbXml)
If success <> 1
Debug CkXmlDSigGen::ckLastErrorText(gen)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
ProcedureReturn
EndIf
; Save the signed XMl to a file.
success = CkStringBuilder::ckWriteFile(sbXml,"qa_output/signedXml.xml","utf-8",0)
; A sample of the signed XML is shown below..
Debug CkStringBuilder::ckGetAsString(sbXml)
; ----------------------------------------
; Verify the signature we just produced...
verifier.i = CkXmlDSig::ckCreate()
If verifier.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
success = CkXmlDSig::ckLoadSignatureSb(verifier,sbXml)
If success <> 1
Debug CkXmlDSig::ckLastErrorText(verifier)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndIf
verified.i = CkXmlDSig::ckVerifySignature(verifier,1)
If verified <> 1
Debug CkXmlDSig::ckLastErrorText(verifier)
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndIf
Debug "This signature was successfully verified."
; -----------------------------------------
; Sample output of AuthNRequest signed XML:
; (Line-breaks and some indenting added for readability..)
; <?xml version="1.0" encoding="utf-8"?>
; <samlp:AuthnRequest
; xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
; xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
; ID="pfx41d8ef22-e612-8c50-9960-1b16f15741b3"
; Version="2.0" ProviderName="SP test"
; IssueInstant="2014-07-16T23:52:45Z"
; Destination="http://idp.example.com/SSOService.php"
; ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
; AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs">
; <saml:Issuer>http://sp.example.com/demo1/metadata.php</saml:Issuer>
; <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
; <samlp:RequestedAuthnContext Comparison="exact">
; <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
; </samlp:RequestedAuthnContext>
; <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#"/>
; <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
; <ds:Reference URI="#pfx41d8ef22-e612-8c50-9960-1b16f15741b3">
; <ds:Transforms>
; <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
; <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
; </ds:Transforms>
; <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
; <ds:DigestValue>5d+/YNShy4qnvZcvik8fHHg2SWQ=</ds:DigestValue>
; </ds:Reference>
; </ds:SignedInfo>
; <ds:SignatureValue>QS16H5...U5LQ==</ds:SignatureValue>
; <ds:KeyInfo>
; <ds:X509Data>
; <ds:X509Certificate>MIIF...tjlF4=</ds:X509Certificate>
; </ds:X509Data>
; </ds:KeyInfo>
; </ds:Signature>
; </samlp:AuthnRequest>
;
CkXml::ckDispose(xmlToSign)
CkXmlDSigGen::ckDispose(gen)
CkCert::ckDispose(cert)
CkStringBuilder::ckDispose(sbXml)
CkXmlDSig::ckDispose(verifier)
ProcedureReturn
EndProcedure