Verifying a signature with X509 certificates.

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 >>>
# Verifying a signature with X509 certificates. ## verify3.c
    /**
     * XML Security Library example: Verifying a file signed with X509 certificate
     *
     * Verifies a file signed with X509 certificate.
     *
     * This example was developed and tested with OpenSSL crypto library. The
     * certificates management policies for another crypto library may break it.
     *
     * Usage:
     *	verify3 <signed-file> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
     *
     * Example:
     *	./verify3 sign3-res.xml rootcert.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/crypto.h>

    xmlSecKeysMngrPtr load_trusted_certs(char** files, int files_size);
    int verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file);

    int
    main(int argc, char **argv) {
        xmlSecKeysMngrPtr mngr;

        assert(argv);

        if(argc < 3) {
    	fprintf(stderr, "Error: wrong number of arguments.\n");
    	fprintf(stderr, "Usage: %s <xml-file> <cert-file1> [<cert-file2> [...]]\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);
        }

        /* create keys manager and load trusted certificates */
        mngr = load_trusted_certs(&(argv[2]), argc - 2);
        if(mngr == NULL) {
    	return(-1);
        }

        /* verify file */
        if(verify_file(mngr, argv[1]) < 0) {
    	xmlSecKeysMngrDestroy(mngr);
    	return(-1);
        }

        /* destroy keys manager */
        xmlSecKeysMngrDestroy(mngr);

        /* 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);
    }

    /**
     * load_trusted_certs:
     * @files:		the list of filenames.
     * @files_size:		the number of filenames in #files.
     *
     * Creates simple keys manager and load trusted certificates from PEM #files.
     * The caller is responsible for destroing returned keys manager using
     * @xmlSecKeysMngrDestroy.
     *
     * Returns the pointer to newly created keys manager or NULL if an error
     * occurs.
     */
    xmlSecKeysMngrPtr
    load_trusted_certs(char** files, int files_size) {
        xmlSecKeysMngrPtr mngr;
        int i;

        assert(files);
        assert(files_size > 0);

        /* create and initialize keys manager, we use a simple list based
         * keys manager, implement your own xmlSecKeysStore klass if you need
         * something more sophisticated
         */
        mngr = xmlSecKeysMngrCreate();
        if(mngr == NULL) {
    	fprintf(stderr, "Error: failed to create keys manager.\n");
    	return(NULL);
        }
        if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
    	fprintf(stderr, "Error: failed to initialize keys manager.\n");
    	xmlSecKeysMngrDestroy(mngr);
    	return(NULL);
        }

        for(i = 0; i < files_size; ++i) {
    	assert(files[i]);

    	/* load trusted cert */
    	if(xmlSecCryptoAppKeysMngrCertLoad(mngr, files[i], xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) {
        	    fprintf(stderr,"Error: failed to load pem certificate from \"%s\"\n", files[i]);
    	    xmlSecKeysMngrDestroy(mngr);
    	    return(NULL);
    	}
        }

        return(mngr);
    }

    /**
     * verify_file:
     * @mngr:		the pointer to keys manager.
     * @xml_file:		the signed XML file name.
     *
     * Verifies XML signature in #xml_file.
     *
     * Returns 0 on success or a negative value if an error occurs.
     */
    int
    verify_file(xmlSecKeysMngrPtr mngr, const char* xml_file) {
        xmlDocPtr doc = NULL;
        xmlNodePtr node = NULL;
        xmlSecDSigCtxPtr dsigCtx = NULL;
        int res = -1;

        assert(mngr);
        assert(xml_file);

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

        /* find start node */
        node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
        if(node == NULL) {
    	fprintf(stderr, "Error: start node not found in \"%s\"\n", xml_file);
    	goto done;
        }

        /* create signature context */
        dsigCtx = xmlSecDSigCtxCreate(mngr);
        if(dsigCtx == NULL) {
            fprintf(stderr,"Error: failed to create signature context\n");
    	goto done;
        }

        /* Verify signature */
        if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
            fprintf(stderr,"Error: signature verify\n");
    	goto done;
        }

        /* print verification result to stdout */
        if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
    	fprintf(stdout, "Signature is OK\n");
        } else {
    	fprintf(stdout, "Signature is INVALID\n");
        }

        /* success */
        res = 0;

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

        if(doc != NULL) {
    	xmlFreeDoc(doc);
        }
        return(res);
    }
<<< Previous Page | Home | Up | Next Page >>>
Verifying a signature with keys manager. | Verifying a signature with additional restrictions.
Aleksey Sanin