[Pyxmlsec-devel] Verifying second signature in document

Ed Shallow ed.shallow at rogers.com
Fri Apr 23 06:45:40 CEST 2004


Hi Valery,

       Things are going well with our testing. I have your library 
behind a Python HTTP Server and things are looking good. I have a more 
advanced verify test of the attached doubly signed xml file. There is a 
signature under the FirstSignature node and another signature under the 
SecondSignature node. I am able to get the verify working OK with the 
xmlsec1 command line utility using ...

xmlsec1 verify --store-references --node-name SecondSignature 
--trusted-der keys/cacert.der inout/edcosigned1-exclude.xml

This verifies OK.

Then I try it with pyxmlsec.

I have changed slightly your verify3.pl to supply sig_node instead of 
start-node. It is attached. It works, but only if I pass in Signature 
and use start_node in the dsig_ctx.verify call. Here is the error I get 
when I try to verify using SecondSignature:

... executing verify operation
func=xmlSecDSigCtxProcessSignatureNode:file=xmldsig.c:line=469:obj=unknown:subj=SecondSignature:error=21:invalid 
node:expected=Signature
func=xmlSecDSigCtxVerify:file=xmldsig.c:line=366:obj=unknown:subj=xmlSecDSigCtxSigantureProcessNode:error=1:xmlsec 
library function failed:
Error: signature verify

I would like to be able to verify the SecondSignature like I am able to 
with the xmlsec1 command line utility. Is Aleksey's command line utility 
doing anything special with the context and node-name that you are doing 
differently ?

Thanks again for your help,
Ed Shallow from Canada

-------------- next part --------------
A non-text attachment was scrubbed...
Name: edcosigned1-exclude.xml
Type: text/xml
Size: 6471 bytes
Desc: not available
Url : http://lists.entrouvert.be/pipermail/pyxmlsec-devel/attachments/20040423/9fc4e2b7/edcosigned1-exclude.xml
-------------- next part --------------
#!/usr/bin/env python
#
# $Id: verify3.py,v 1.7 2004/01/05 17:58:18 valos Exp $
#
# PyXMLSec 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.py <signed-file> <node-name> <trusted-cert-pem-file1> [<trusted-cert-pem-file2> [...]]
#
# Example:
#	./verify3.py sign3-res.xml FirstSignature cacert.pem
#
# This is free software; see COPYING file in the source
# distribution for preciese wording.
# 
# Copyright (C) 2003-2004 Valery Febvre <vfebvre at easter-eggs.com>
#

import sys, os
sys.path.insert(0, '../')

import libxml2
import xmlsec

def main():
    assert(sys.argv)
    if len(sys.argv) < 4:
        print "Error: wrong number of arguments."
        print "Usage: %s <xml-file> <node-name> <cert-file1> [<cert-file2> [...]]" % sys.argv[0]
        return sys.exit(1)
    
    # Init libxml library
    libxml2.initParser()
    libxml2.substituteEntitiesDefault(1)

    # Init xmlsec library
    if xmlsec.init() < 0:
        print "Error: xmlsec initialization failed."
        return sys.exit(-1)
    
    # Check loaded library version
    if xmlsec.checkVersion() != 1:
	print "Error: loaded xmlsec library version is not compatible.\n"
	sys.exit(-1)

    # Init crypto library
    if xmlsec.cryptoAppInit(None) < 0:
        print "Error: crypto initialization failed."
    
    # Init xmlsec-crypto library
    if xmlsec.cryptoInit() < 0:
        print "Error: xmlsec-crypto initialization failed."

    # Create keys manager and load trusted certificates
    # Starting from 3rd argument to the end of the list
    mngr = load_trusted_certs(sys.argv[3:], len(sys.argv) - 3)

    # Verify file
    if mngr is not None:
        res = verify_file(mngr, sys.argv[1], sys.argv[2])
        # Destroy keys manager
        mngr.destroy()
    
    # Shutdown xmlsec-crypto library
    xmlsec.cryptoShutdown()

    # Shutdown crypto library
    xmlsec.cryptoAppShutdown()

    # Shutdown xmlsec library
    xmlsec.shutdown()

    # Shutdown LibXML2
    libxml2.cleanupParser()

    sys.exit(res)


# Creates simple keys manager and load trusted certificates from PEM files.
# The caller is responsible for destroying returned keys manager using
# destroy method.
#
# Returns the newly created keys manager or None if an error occurs.
def load_trusted_certs(files, files_size):
    assert(files)
    assert(files_size > 0)

    # Create and initialize keys manager, we use a simple list based
    # keys manager, implement your own KeysStore klass if you need
    # something more sophisticated
    mngr = xmlsec.KeysMngr()
    if mngr is None:
        print "Error: failed to create keys manager."
        return None
    if xmlsec.cryptoAppDefaultKeysMngrInit(mngr) < 0:
        print "Error: failed to initialize keys manager."
        mngr.destroy()
        return None
    for file in files:
        if not check_filename(file):
            mngr.destroy()
            return None
        # Load trusted cert
        if mngr.certLoad(file, xmlsec.KeyDataFormatPem,
                         xmlsec.KeyDataTypeTrusted) < 0:
            print "Error: failed to load pem certificate from \"%s\"", file
            mngr.destroy()
            return None
    return mngr


# Verifies XML signature in xml_file.
# Returns 0 on success or a negative value if an error occurs.
def verify_file(mngr, xml_file, node_name):
    assert(mngr)
    assert(xml_file)

    # Load XML file
    if not check_filename(xml_file):
        return -1
    doc = libxml2.parseFile(xml_file)
    if doc is None or doc.getRootElement() is None:
	print "Error: unable to parse file \"%s\"" % tmpl_file
        return cleanup(doc)

    # Find start node
    start_node = xmlsec.findNode(doc.getRootElement(),
                           xmlsec.NodeSignature, xmlsec.DSigNs)
    if start_node is None:
        print "Error: start node", xmlsec.NodeSignature, "not found in \"%s\"", xml_file

    sig_node = xmlsec.findNode(doc.getRootElement(),
                           node_name, None)
    if sig_node is None:
        print "Error: signature node", node_name, "not found in \"%s\"", xml_file

    # Create signature context
    dsig_ctx = xmlsec.DSigCtx(mngr)
    if dsig_ctx is None:
        print "Error: failed to create signature context"
        return cleanup(doc)

    # Verify signature
    if dsig_ctx.verify(start_node) < 0:
        print "Error: signature verify"
        return cleanup(doc, dsig_ctx)

    # Print verification result to stdout
    if dsig_ctx.status == xmlsec.DSigStatusSucceeded:
        print "Signature is OK"
    else:
        print "Signature is INVALID"

    # Success
    return cleanup(doc, dsig_ctx, 1)


def cleanup(doc=None, dsig_ctx=None, res=-1):
    if dsig_ctx is not None:
        dsig_ctx.destroy()
    if doc is not None:
        doc.freeDoc()
    return res


def check_filename(filename):
    if os.access(filename, os.R_OK):
        return 1
    else:
        print "Error: XML file \"%s\" not found OR no read access" % filename
        return 0


if __name__ == "__main__":
    main()


More information about the Pyxmlsec-devel mailing list