Signing a dynamicaly created template.

Home Download News Documentation FAQ Tutorial API reference Examples XML Digital Signature Online Verifier XML Encryption XML Canonicalization Reporting Bugs Mailing list Related
XML Security Library Reference Manual
<<< Previous Page | Home | Up | Next Page >>>
# Signing a dynamicaly created template. ## sign2.c
    /**
     * XML Security Library example: Signing a file with a dynamicaly created template.
     *
     * Signs a file using a dynamicaly created template and key from PEM file.
     * The signature has one reference with one enveloped transform to sign
     * the whole document except the <dsig:Signature/> node itself.
     *
     * Usage:
     *	sign2 <xml-doc> <pem-key>
     *
     * Example:
     *	./sign2 sign2-doc.xml rsakey.pem > sign2-res.xml
     *
     * The result signature could be validated using verify1 example:
     *	./verify1 sign2-res.xml rsapub.pem
     *
     * This is free software; see Copyright file in the source
     * distribution for preciese wording.
     *
     * Copyrigth (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
     */
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>

    #include <libxml/tree.h>
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>

    #ifndef XMLSEC_NO_XSLT
    #include <libxslt/xslt.h>
    #endif /* XMLSEC_NO_XSLT */

    #include <xmlsec/xmlsec.h>
    #include <xmlsec/xmltree.h>
    #include <xmlsec/xmldsig.h>
    #include <xmlsec/templates.h>
    #include <xmlsec/crypto.h>

    int sign_file(const char* xml_file, const char* key_file);

    int
    main(int argc, char **argv) {
        assert(argv);

        if(argc != 3) {
    	fprintf(stderr, "Error: wrong number of arguments.\n");
    	fprintf(stderr, "Usage: %s <xml-file> <key-file>\n", argv[0]);
    	return(1);
        }

        /* Init libxml and libxslt libraries */
        xmlInitParser();
        LIBXML_TEST_VERSION
        xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
        xmlSubstituteEntitiesDefault(1);
    #ifndef XMLSEC_NO_XSLT
        xmlIndentTreeOutput = 1;
    #endif /* XMLSEC_NO_XSLT */

        /* Init xmlsec library */
        if(xmlSecInit() < 0) {
    	fprintf(stderr, "Error: xmlsec initialization failed.\n");
    	return(-1);
        }

        /* Init crypto library */
        if(xmlSecCryptoAppInit(NULL) < 0) {
    	fprintf(stderr, "Error: crypto initialization failed.\n");
    	return(-1);
        }

        /* Init xmlsec-crypto library */
        if(xmlSecCryptoInit() < 0) {
    	fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
    	return(-1);
        }

        if(sign_file(argv[1], argv[2]) < 0) {
    	return(-1);
        }

        /* Shutdown xmlsec-crypto library */
        xmlSecCryptoShutdown();

        /* Shutdown crypto library */
        xmlSecCryptoAppShutdown();

        /* Shutdown xmlsec library */
        xmlSecShutdown();

        /* Shutdown libxslt/libxml */
    #ifndef XMLSEC_NO_XSLT
        xsltCleanupGlobals();
    #endif /* XMLSEC_NO_XSLT */
        xmlCleanupParser();

        return(0);
    }

    /**
     * sign_file:
     * @xml_file:		the XML file name.
     * @key_file:		the PEM private key file name.
     *
     * Signs the #xml_file using private key from #key_file and dynamicaly
     * created enveloped signature template.
     *
     * Returns 0 on success or a negative value if an error occurs.
     */
    int
    sign_file(const char* xml_file, const char* key_file) {
        xmlDocPtr doc = NULL;
        xmlNodePtr signNode = NULL;
        xmlNodePtr refNode = NULL;
        xmlNodePtr keyInfoNode = NULL;
        xmlSecDSigCtxPtr dsigCtx = NULL;
        int res = -1;

        assert(xml_file);
        assert(key_file);

        /* load doc file */
        doc = xmlParseFile(xml_file);
        if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
    	fprintf(stderr, "Error: unable to parse file \"%s\"\n", xml_file);
    	goto done;
        }

        /* create signature template for RSA-SHA1 enveloped signature */
        signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
    				         xmlSecTransformRsaSha1Id, NULL);
        if(signNode == NULL) {
    	fprintf(stderr, "Error: failed to create signature template\n");
    	goto done;
        }

        /* add <dsig:Signature/> node to the doc */
        xmlAddChild(xmlDocGetRootElement(doc), signNode);

        /* add reference */
        refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
    					NULL, NULL, NULL);
        if(refNode == NULL) {
    	fprintf(stderr, "Error: failed to add reference to signature template\n");
    	goto done;
        }

        /* add enveloped transform */
        if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
    	fprintf(stderr, "Error: failed to add enveloped transform to reference\n");
    	goto done;
        }

        /* add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed document */
        keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
        if(keyInfoNode == NULL) {
    	fprintf(stderr, "Error: failed to add key info\n");
    	goto done;
        }

        if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
    	fprintf(stderr, "Error: failed to add key name\n");
    	goto done;
        }

        /* create signature context, we don't need keys manager in this example */
        dsigCtx = xmlSecDSigCtxCreate(NULL);
        if(dsigCtx == NULL) {
            fprintf(stderr,"Error: failed to create signature context\n");
    	goto done;
        }

        /* load private key, assuming that there is not password */
        dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
        if(dsigCtx->signKey == NULL) {
            fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
    	goto done;
        }

        /* set key name to the file name, this is just an example! */
        if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
        	fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
    	goto done;
        }

        /* sign the template */
        if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
            fprintf(stderr,"Error: signature failed\n");
    	goto done;
        }

        /* print signed document to stdout */
        xmlDocDump(stdout, doc);

        /* success */
        res = 0;

    done:
        /* cleanup */
        if(dsigCtx != NULL) {
    	xmlSecDSigCtxDestroy(dsigCtx);
        }

        if(doc != NULL) {
    	xmlFreeDoc(doc);
        }
        return(res);
    }
## sign2-doc.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    XML Security Library example: Original XML doc file for sign2 example.
    -->
    <Envelope xmlns="urn:envelope">
      <Data>
    	Hello, World!
      </Data>
    </Envelope>
## sign2-res.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    XML Security Library example: Signed XML doc file (sign2 example).
    -->
    <Envelope xmlns="urn:envelope">
      <Data>
    	Hello, World!
      </Data>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <Reference>
    <Transforms>
    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <DigestValue>HjY8ilZAIEM2tBbPn5mYO1ieIX4=</DigestValue>
    </Reference>
    </SignedInfo>
    <SignatureValue>SIaj/6KY3C1SmDXU2++Gm31U1xTadFp04WhBgfsJFbxrL+q7GKSKN9kfQ+UpN9+i
    D5fWmuavXEHe4Gw6RMaMEkq2URQo7F68+d5J/ajq8/l4n+xE6/reGScVwT6L4dEP
    XXVJcAi2ZnQ3O7GTNvNGCPibL9mUcyCWBFZ92Uemtc/vJFCQ7ZyKMdMfACgxOwyN
    T/9971oog241/2doudhonc0I/3mgPYWkZdX6yvr62mEjnG+oUZkhWYJ4ewZJ4hM4
    JjbFqZO+OEzDRSbw3DkmuBA/mtlx+3t13SESfEub5hqoMdVmtth/eTb64dsPdl9r
    3k1ACVX9f8aHfQQdJOmLFQ==</SignatureValue>
    <KeyInfo>
    <KeyName>rsakey.pem</KeyName>
    </KeyInfo>
    </Signature></Envelope>
<<< Previous Page | Home | Up | Next Page >>>
Signing a template file. | Signing with X509 certificate.
Aleksey Sanin