Unicode C
Unicode C
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 Unicode C Downloads
#include <C_CkXmlW.h>
#include <C_CkXmlDSigGenW.h>
#include <C_CkCertW.h>
#include <C_CkStringBuilderW.h>
#include <C_CkXmlDSigW.h>
void ChilkatSample(void)
{
BOOL success;
HCkXmlW xmlToSign;
HCkXmlDSigGenW gen;
HCkCertW cert;
HCkStringBuilderW sbXml;
HCkXmlDSigW verifier;
BOOL verified;
success = FALSE;
// 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 = TRUE;
xmlToSign = CkXmlW_Create();
CkXmlW_putTag(xmlToSign,L"samlp:AuthnRequest");
CkXmlW_AddAttribute(xmlToSign,L"xmlns:samlp",L"urn:oasis:names:tc:SAML:2.0:protocol");
CkXmlW_AddAttribute(xmlToSign,L"xmlns:saml",L"urn:oasis:names:tc:SAML:2.0:assertion");
CkXmlW_AddAttribute(xmlToSign,L"ID",L"pfx41d8ef22-e612-8c50-9960-1b16f15741b3");
CkXmlW_AddAttribute(xmlToSign,L"Version",L"2.0");
CkXmlW_AddAttribute(xmlToSign,L"ProviderName",L"SP test");
CkXmlW_AddAttribute(xmlToSign,L"IssueInstant",L"2014-07-16T23:52:45Z");
CkXmlW_AddAttribute(xmlToSign,L"Destination",L"http://idp.example.com/SSOService.php");
CkXmlW_AddAttribute(xmlToSign,L"ProtocolBinding",L"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
CkXmlW_AddAttribute(xmlToSign,L"AssertionConsumerServiceURL",L"http://sp.example.com/demo1/index.php?acs");
CkXmlW_UpdateChildContent(xmlToSign,L"saml:Issuer",L"http://sp.example.com/demo1/metadata.php");
CkXmlW_UpdateAttrAt(xmlToSign,L"samlp:NameIDPolicy",TRUE,L"Format",L"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
CkXmlW_UpdateAttrAt(xmlToSign,L"samlp:NameIDPolicy",TRUE,L"AllowCreate",L"true");
CkXmlW_UpdateAttrAt(xmlToSign,L"samlp:RequestedAuthnContext",TRUE,L"Comparison",L"exact");
CkXmlW_UpdateChildContent(xmlToSign,L"samlp:RequestedAuthnContext|saml:AuthnContextClassRef",L"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 = CkXmlDSigGenW_Create();
CkXmlDSigGenW_putSigLocation(gen,L"samlp:AuthnRequest");
CkXmlDSigGenW_putSigNamespacePrefix(gen,L"ds");
CkXmlDSigGenW_putSigNamespaceUri(gen,L"http://www.w3.org/2000/09/xmldsig#");
CkXmlDSigGenW_putSignedInfoCanonAlg(gen,L"EXCL_C14N");
CkXmlDSigGenW_putSignedInfoDigestMethod(gen,L"sha1");
// -------- Reference 1 --------
CkXmlDSigGenW_AddSameDocRef(gen,L"pfx41d8ef22-e612-8c50-9960-1b16f15741b3",L"sha1",L"EXCL_C14N",L"",L"");
// Provide a certificate + private key. (PFX password is test123)
cert = CkCertW_Create();
success = CkCertW_LoadPfxFile(cert,L"qa_data/pfx/cert_test123.pfx",L"test123");
if (success != TRUE) {
wprintf(L"%s\n",CkCertW_lastErrorText(cert));
CkXmlW_Dispose(xmlToSign);
CkXmlDSigGenW_Dispose(gen);
CkCertW_Dispose(cert);
return;
}
CkXmlDSigGenW_SetX509Cert(gen,cert,TRUE);
CkXmlDSigGenW_putKeyInfoType(gen,L"X509Data");
CkXmlDSigGenW_putX509Type(gen,L"Certificate");
// Load XML to be signed...
sbXml = CkStringBuilderW_Create();
CkXmlW_GetXmlSb(xmlToSign,sbXml);
CkXmlDSigGenW_putBehaviors(gen,L"IndentedSignature,ForceAddEnvelopedSignatureTransform");
// Sign the XML...
success = CkXmlDSigGenW_CreateXmlDSigSb(gen,sbXml);
if (success != TRUE) {
wprintf(L"%s\n",CkXmlDSigGenW_lastErrorText(gen));
CkXmlW_Dispose(xmlToSign);
CkXmlDSigGenW_Dispose(gen);
CkCertW_Dispose(cert);
CkStringBuilderW_Dispose(sbXml);
return;
}
// Save the signed XMl to a file.
success = CkStringBuilderW_WriteFile(sbXml,L"qa_output/signedXml.xml",L"utf-8",FALSE);
// A sample of the signed XML is shown below..
wprintf(L"%s\n",CkStringBuilderW_getAsString(sbXml));
// ----------------------------------------
// Verify the signature we just produced...
verifier = CkXmlDSigW_Create();
success = CkXmlDSigW_LoadSignatureSb(verifier,sbXml);
if (success != TRUE) {
wprintf(L"%s\n",CkXmlDSigW_lastErrorText(verifier));
CkXmlW_Dispose(xmlToSign);
CkXmlDSigGenW_Dispose(gen);
CkCertW_Dispose(cert);
CkStringBuilderW_Dispose(sbXml);
CkXmlDSigW_Dispose(verifier);
return;
}
verified = CkXmlDSigW_VerifySignature(verifier,TRUE);
if (verified != TRUE) {
wprintf(L"%s\n",CkXmlDSigW_lastErrorText(verifier));
CkXmlW_Dispose(xmlToSign);
CkXmlDSigGenW_Dispose(gen);
CkCertW_Dispose(cert);
CkStringBuilderW_Dispose(sbXml);
CkXmlDSigW_Dispose(verifier);
return;
}
wprintf(L"This signature was successfully verified.\n");
// -----------------------------------------
// 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>
//
CkXmlW_Dispose(xmlToSign);
CkXmlDSigGenW_Dispose(gen);
CkCertW_Dispose(cert);
CkStringBuilderW_Dispose(sbXml);
CkXmlDSigW_Dispose(verifier);
}