source: TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/sign3-usingTmpl.py @ 7080

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/sign3-usingTmpl.py
Revision 7080, 6.3 KB checked in by pjkersha, 9 years ago (diff)
  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2#
3# $Id$
4#
5# PyXMLSec example: Signing a file with a dynamicaly created template and
6# an X509 certificate.
7#
8# Signs a file using a dynamicaly created template, key from PEM file and
9# an X509 certificate. The signature has one reference with one enveloped
10# transform to sign the whole document except the <dsig:Signature/> node
11# itself. The key certificate is written in the <dsig:X509Data/> node.
12#
13# This example was developed and tested with OpenSSL crypto library. The
14# certificates management policies for another crypto library may break it.
15#
16# Usage:
17#       ./sign3.py <xml-doc> <key-file> <cert-file>
18#
19# Example:
20#       ./sign3.py sign3-doc.xml rsakey.pem rsacert.pem > sign3-res.xml
21#
22# The result signature could be validated using verify3 example:
23#       ./verify3.py sign3-res.xml rootcert.pem
24#
25# This is free software; see COPYING file in the source
26# distribution for preciese wording.
27#
28# Copyright (C) 2003-2004 Valery Febvre <vfebvre@easter-eggs.com>
29#
30
31import os, sys
32sys.path.insert(0, '../')
33
34import libxml2
35import xmlsec
36import pdb
37
38def main():
39    assert(sys.argv)
40    if len(sys.argv) < 4:
41        print "Error: wrong number of arguments."
42        print "Usage: %s <xml-tmpl> <key-file> <cert-file>" % sys.argv[0]
43        return sys.exit(1)
44   
45    # Init libxml library
46    libxml2.initParser()
47    libxml2.substituteEntitiesDefault(1)
48
49    # Init xmlsec library
50    if xmlsec.init() < 0:
51        print "Error: xmlsec initialization failed."
52        return sys.exit(-1)
53   
54    # Check loaded library version
55    if xmlsec.checkVersion() != 1:
56        print "Error: loaded xmlsec library version is not compatible.\n"
57        sys.exit(-1)
58
59    # Init crypto library
60    if xmlsec.cryptoAppInit(None) < 0:
61        print "Error: crypto initialization failed."
62   
63    # Init xmlsec-crypto library
64    if xmlsec.cryptoInit() < 0:
65        print "Error: xmlsec-crypto initialization failed."
66
67    res = sign_file(sys.argv[1], sys.argv[2], sys.argv[3])
68
69    # Shutdown xmlsec-crypto library
70    xmlsec.cryptoShutdown()
71
72    # Shutdown crypto library
73    xmlsec.cryptoAppShutdown()
74
75    # Shutdown xmlsec library
76    xmlsec.shutdown()
77
78    # Shutdown LibXML2
79    libxml2.cleanupParser()
80
81    sys.exit(res)
82
83
84# Signs the xml_file using private key from key_file and dynamicaly
85# created enveloped signature template. The certificate from cert_file
86# is placed in the <dsig:X509Data/> node.
87# Returns 0 on success or a negative value if an error occurs.
88def sign_file(xml_file, key_file, cert_file):
89    assert(xml_file)
90    assert(key_file)
91    assert(cert_file)
92
93    # Load template
94    if not check_filename(xml_file):
95        return -1
96    doc = libxml2.parseFile(xml_file)
97    if doc is None or doc.getRootElement() is None:
98        print "Error: unable to parse file \"%s\"" % xml_file
99        return cleanup(doc)
100   
101    # Find start node
102    signNode = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature,
103                               xmlsec.DSigNs)
104    if signNode is None:
105        print "Error: start node not found in \"%s\"" % xml_file
106        return cleanup(doc)
107
108    # Create signature template for RSA-SHA1 enveloped signature
109##    signNode = xmlsec.TmplSignature(doc, xmlsec.transformExclC14NId(),
110##                                    xmlsec.transformRsaSha1Id(), None)
111##    if signNode is None:
112##        print "Error: failed to create signature template"
113##        return cleanup(doc)
114##   
115##    # Add <dsig:Signature/> node to the doc
116##    doc.getRootElement().addChild(signNode)
117##
118##    # Add reference
119##    refNode = signNode.addReference(xmlsec.transformSha1Id(),
120##                                    None, None, None)
121##    if refNode is None:
122##        print "Error: failed to add reference to signature template"
123##        return cleanup(doc)
124##
125##    # Add enveloped transform
126##    if refNode.addTransform(xmlsec.transformEnvelopedId()) is None:
127##        print "Error: failed to add enveloped transform to reference"
128##        return cleanup(doc)
129##
130##    # Add <dsig:KeyInfo/> and <dsig:X509Data/>
131##    keyInfoNode = signNode.ensureKeyInfo(None)
132##    if keyInfoNode is None:
133##        print "Error: failed to add key info"
134##        return cleanup(doc)
135##
136##    # P J Kershaw 11/08/05
137##    if keyInfoNode.addKeyName() is None:
138##        print "Error: failed to add KeyName node"
139##        return cleanup(doc)
140##
141####    if keyInfoNode.addKeyValue() is None:
142####        print "Error: failed to add KeyValue node"
143####        return cleanup(doc)
144##   
145##    if keyInfoNode.addX509Data() is None:
146##        print "Error: failed to add X509Data node"
147##        return cleanup(doc)
148
149    # Create signature context, we don't need keys manager in this example
150    dsig_ctx = xmlsec.DSigCtx()
151    if dsig_ctx is None:
152        print "Error: failed to create signature context"
153        return cleanup(doc)
154
155   
156    # Load private key, assuming that there is not password
157    if not check_filename(key_file):
158        return cleanup(doc, dsig_ctx)
159    key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem,
160                                  None, None, None)
161    if key is None:
162        print "Error: failed to load private pem key from \"%s\"" % key_file
163        return cleanup(doc, dsig_ctx)
164    dsig_ctx.signKey = key
165
166    # Load certificate and add to the key
167    if not check_filename(cert_file):
168        return cleanup(doc, dsig_ctx)
169    if xmlsec.cryptoAppKeyCertLoad(key, cert_file, xmlsec.KeyDataFormatPem) < 0:
170        print "Error: failed to load pem certificate \"%s\"" % cert_file
171        return cleanup(doc, dsig_ctx)
172
173    # Set key name to the file name, this is just an example!
174    if key.setName(key_file) < 0:
175        print "Error: failed to set key name for key from \"%s\"" % key_file
176        return cleanup(doc, dsig_ctx)
177
178    # Sign the template
179    if dsig_ctx.sign(signNode) < 0:
180        print "Error: signature failed"
181        return cleanup(doc, dsig_ctx)
182
183    # Print signed document to stdout
184    doc.dump("-")
185
186    # Success
187    return cleanup(doc, dsig_ctx, 1)
188
189
190def cleanup(doc=None, dsig_ctx=None, res=-1):
191    if dsig_ctx is not None:
192        dsig_ctx.destroy()
193    if doc is not None:
194        doc.freeDoc()
195    return res
196
197
198def check_filename(filename):
199    if os.access(filename, os.R_OK):
200        return 1
201    else:
202        print "Error: XML file \"%s\" not found OR no read access" % filename
203        return 0
204
205
206if __name__ == "__main__":
207    main()
208
Note: See TracBrowser for help on using the repository browser.