Verifying a signed document: XML Security Library Reference Manual

## Verifying a signed document

The typical signature verification process includes following steps:

- Load keys, X509 certificates, etc. in the keys manager .

- Create signature context xmlSecDSigCtx using xmlSecDSigCtxCreate or xmlSecDSigCtxInitialize functions.

- Select start verification <dsig:Signature/> node in the signed XML document.

- Verify signature by calling xmlSecDSigCtxVerify function.

- Check returned value and verification status (`status` member of xmlSecDSigCtx structure). If necessary, consume returned data from the context.

- Destroy signature context xmlSecDSigCtx using xmlSecDSigCtxDestroy or xmlSecDSigCtxFinalize functions.

Example 14. Verifying a document.

    /**
     * verify_file:
     * @xml_file:		the signed XML file name.
     * @key_file:		the PEM public key file name.
     *
     * Verifies XML signature in #xml_file using public key from #key_file.
     *
     * Returns 0 on success or a negative value if an error occurs.
     */
    int
    verify_file(const char* xml_file, const char* key_file) {
        xmlDocPtr doc = NULL;
        xmlNodePtr node = NULL;
        xmlSecDSigCtxPtr dsigCtx = NULL;
        int res = -1;

        assert(xml_file);
        assert(key_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, 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 public key */
        dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file,xmlSecKeyDataFormatPem, NULL, NULL, NULL);
        if(dsigCtx->signKey == NULL) {
            fprintf(stderr,"Error: failed to load public 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;
        }

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

Full Program Listing