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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/decrypt3.py@7080
Revision 7080, 6.4 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: Decrypting an encrypted file using a custom keys manager.
6#
7# Decrypts encrypted XML file using a custom files based keys manager.
8# We assume that key's name in <dsig:KeyName/> element is just
9# key's file name in the current folder.
10#
11# Usage:
12#       ./decrypt3.py <xml-enc>
13#
14# Example:
15#       ./decrypt3.py encrypt1-res.xml
16#       ./decrypt3.py encrypt2-res.xml
17#
18# This is free software; see COPYING file in the source
19# distribution for preciese wording.
20#
21# Copyright (C) 2003-2004 Valery Febvre <vfebvre@easter-eggs.com>
22#
23
24import os, sys
25sys.path.insert(0, '../')
26
27import libxml2
28import xmlsec
29
30def main():
31    assert(sys.argv)
32    if len(sys.argv) != 2:
33        print "Error: wrong number of arguments."
34        print "Usage: %s <enc-file>" % sys.argv[0]
35        return sys.exit(1)
36   
37    res = 0
38    # Init libxml library
39    libxml2.initParser()
40    libxml2.substituteEntitiesDefault(1)
41
42    # Init xmlsec library
43    if xmlsec.init() < 0:
44        print "Error: xmlsec initialization failed."
45        return sys.exit(-1)
46   
47    # Check loaded library version
48    if xmlsec.checkVersion() != 1:
49        print "Error: loaded xmlsec library version is not compatible."
50        sys.exit(-1)
51
52    # Init crypto library
53    if xmlsec.cryptoAppInit(None) < 0:
54        print "Error: crypto initialization failed."
55   
56    # Init xmlsec-crypto library
57    if xmlsec.cryptoInit() < 0:
58        print "Error: xmlsec-crypto initialization failed."
59
60    # Create keys manager and load keys */
61    mngr = create_files_keys_mngr()
62
63    if mngr is not None:
64        res = decrypt_file(mngr, sys.argv[1])
65
66    # Shutdown xmlsec-crypto library
67    xmlsec.cryptoShutdown()
68
69    # Shutdown crypto library
70    xmlsec.cryptoAppShutdown()
71
72    # Shutdown xmlsec library
73    xmlsec.shutdown()
74
75    # Shutdown LibXML2
76    libxml2.cleanupParser()
77
78    sys.exit(res)
79
80
81# Callback function
82def getKeyCallback(keyInfoNode, keyInfoCtx):
83    # Convert PyCObject object into xmlNode and KeyInfoCtx Objects
84    node = libxml2.xmlNode(_obj=keyInfoNode)
85    ctx = xmlsec.KeyInfoCtx(_obj=keyInfoCtx)
86    return xmlsec.keysMngrGetKey(node, ctx)
87
88
89# Creates a files based keys manager
90# we assume that key name is the key file name
91# Returns newly created keys manager or None if an error occurs.
92def create_files_keys_mngr():
93    # Create files based keys store
94    storeId = xmlsec.KeyStoreId(0, 0, "files-based-keys-store",
95                                None, None, files_keys_store_find_key)
96    keysStore = xmlsec.KeyStore(storeId)
97
98    if keysStore is None:
99        print "Error: failed to create keys store."
100        return None
101   
102    # Create keys manager
103    mngr = xmlsec.KeysMngr()
104    if mngr is None:
105        print "Error: failed to create keys manager."
106        keysStore.destroy()
107        return None
108
109    # Add store to keys manager, from now on keys manager destroys the store
110    # if needed
111    if mngr.adoptKeysStore(keysStore) < 0:
112        print "Error: failed to add keys store to keys manager."
113        keysStore.destroy()
114        mngr.destroy()
115        return None
116   
117    # Initialize crypto library specific data in keys manager
118    if xmlsec.cryptoKeysMngrInit(mngr) < 0:
119        print "Error: failed to initialize crypto data in keys manager."
120        keysStore.destroy()
121        mngr.destroy()
122        return None
123
124    # Set the get key callback
125    mngr.getKey = getKeyCallback
126    return mngr
127
128
129# Decrypts the XML file enc_file using DES key files in mngr and
130# prints results to stdout.
131#
132# Returns 0 on success or a negative value if an error occurs.
133def decrypt_file(mngr, enc_file):
134    assert(mngr)
135    assert(enc_file)
136
137    # Load template
138    if not check_filename(enc_file):
139        return -1
140    doc = libxml2.parseFile(enc_file)
141    if doc is None or doc.getRootElement() is None:
142        print "Error: unable to parse file \"%s\"" % enc_file
143        return cleanup(doc)
144   
145    # Find start node
146    node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData,
147                           xmlsec.EncNs)
148    if node is None:
149        print "Error: start node not found in \"%s\"" % tmpl_file
150        return cleanup(doc)
151   
152    # Create encryption context
153    enc_ctx = xmlsec.EncCtx(mngr)
154    if enc_ctx is None:
155        print "Error: failed to create encryption context"
156        return cleanup(doc)
157
158    # Decrypt the data
159    if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None:
160        print "Error: decryption failed"
161        return cleanup(doc, enc_ctx)
162
163    # Print decrypted data to stdout
164    if enc_ctx.resultReplaced != 0:
165        print "Decrypted XML data:"
166        doc.dump("-")
167    else:
168        print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize()
169        print enc_ctx.result.getData()
170
171    # Success
172    return cleanup(doc, enc_ctx, 1)
173
174
175# Lookups key in the store. The caller is responsible for destroying
176# returned key with destroy method.
177#
178# Returns key or None if key not found or an error occurs.
179def files_keys_store_find_key(store, name, keyInfoCtx):
180    assert(store)
181    assert(keyInfoCtx)
182   
183    ctx = xmlsec.KeyInfoCtx(_obj=keyInfoCtx)
184   
185    # It's possible to do not have the key name or desired key type
186    # but we could do nothing in this case
187    if name is None or ctx.keyReq.keyId == xmlsec.KeyDataIdUnknown:
188        print "Return None"
189        return None
190   
191    if ctx.keyReq.keyId == xmlsec.keyDataDsaId() or ctx.keyReq.keyId == xmlsec.keyDataRsaId():
192        # Load key from a pem file, if key is not found then it's an error (is it?)
193        key = xmlsec.CryptoAppKeyLoad(name, xmlsec.KeyDataFormatPem, None, None, None)
194        if key is None:
195            print "Error: failed to load public pem key from \"%s\"" % name
196            return None
197    else:
198        # Otherwise it's a binary key, if key is not found then it's an error (is it?)
199        key = xmlsec.keyReadBinaryFile(ctx.keyReq.keyId, name)
200        if key is None:
201            print "Error: failed to load key from binary file \"%s\"" % name
202            return None
203   
204    # Set key name
205    if key.setName(name) < 0:
206        print "Error: failed to set key name for key from \"%s\"" % name
207        key.destroy();
208        return None
209   
210    return key
211
212
213def cleanup(doc=None, enc_ctx=None, res=-1):
214    if enc_ctx is not None:
215        enc_ctx.destroy()
216    if doc is not None:
217        doc.freeDoc()
218    return res
219
220
221def check_filename(filename):
222    if os.access(filename, os.R_OK):
223        return 1
224    else:
225        print "Error: XML file \"%s\" not found OR no read access" % filename
226        return 0
227
228
229if __name__ == "__main__":
230    main()
Note: See TracBrowser for help on using the repository browser.