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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/Tests/xmlsec/decrypt4.py@7080
Revision 7080, 7.9 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) != 3:
33        print "Error: wrong number of arguments."
34        print "Usage: %s <enc-file> <private key 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 and initialize keys manager
61    #mngr = create_files_keys_mngr()
62    mngr = loadPriKey(sys.argv[2])
63   
64    if mngr is not None:
65        res = decrypt_file(mngr, sys.argv[1])
66
67    # Shutdown xmlsec-crypto library
68    xmlsec.cryptoShutdown()
69
70    # Shutdown crypto library
71    xmlsec.cryptoAppShutdown()
72
73    # Shutdown xmlsec library
74    xmlsec.shutdown()
75
76    # Shutdown LibXML2
77    libxml2.cleanupParser()
78
79    sys.exit(res)
80
81
82# Callback function
83def getKeyCallback(keyInfoNode, keyInfoCtx):
84    # Convert PyCObject object into xmlNode and KeyInfoCtx Objects
85    node = libxml2.xmlNode(_obj=keyInfoNode)
86    ctx = xmlsec.KeyInfoCtx(_obj=keyInfoCtx)
87    return xmlsec.keysMngrGetKey(node, ctx)
88
89
90# Creates a files based keys manager
91# we assume that key name is the key file name
92# Returns newly created keys manager or None if an error occurs.
93def create_files_keys_mngr():
94    # Create files based keys store
95    storeId = xmlsec.KeyStoreId(0, 0, "files-based-keys-store",
96                                None, None, files_keys_store_find_key)
97    keysStore = xmlsec.KeyStore(storeId)
98
99    if keysStore is None:
100        print "Error: failed to create keys store."
101        return None
102   
103    # Create keys manager
104    mngr = xmlsec.KeysMngr()
105    if mngr is None:
106        print "Error: failed to create keys manager."
107        keysStore.destroy()
108        return None
109
110    # Add store to keys manager, from now on keys manager destroys the store
111    # if needed
112    if mngr.adoptKeysStore(keysStore) < 0:
113        print "Error: failed to add keys store to keys manager."
114        keysStore.destroy()
115        mngr.destroy()
116        return None
117   
118    # Initialize crypto library specific data in keys manager
119    if xmlsec.cryptoKeysMngrInit(mngr) < 0:
120        print "Error: failed to initialize crypto data in keys manager."
121        keysStore.destroy()
122        mngr.destroy()
123        return None
124
125    # Set the get key callback
126    mngr.getKey = getKeyCallback
127    return mngr
128
129
130# Decrypts the XML file enc_file using DES key files in mngr and
131# prints results to stdout.
132#
133# Returns 0 on success or a negative value if an error occurs.
134def decrypt_file(mngr, enc_file):
135    assert(mngr)
136    assert(enc_file)
137
138    # Load template
139    if not check_filename(enc_file):
140        return -1
141    doc = libxml2.parseFile(enc_file)
142    if doc is None or doc.getRootElement() is None:
143        print "Error: unable to parse file \"%s\"" % enc_file
144        return cleanup(doc)
145   
146    # Find start node
147    node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData,
148                           xmlsec.EncNs)
149    if node is None:
150        print "Error: start node not found in \"%s\"" % tmpl_file
151        return cleanup(doc)
152   
153    # Create encryption context
154    enc_ctx = xmlsec.EncCtx(mngr)
155    if enc_ctx is None:
156        print "Error: failed to create encryption context"
157        return cleanup(doc)
158
159    # Decrypt the data
160    if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None:
161        print "Error: decryption failed"
162        return cleanup(doc, enc_ctx)
163
164    # Print decrypted data to stdout
165    if enc_ctx.resultReplaced != 0:
166        print "Decrypted XML data:"
167        doc.dump("-")
168    else:
169        print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize()
170        print enc_ctx.result.getData()
171
172    # Success
173    return cleanup(doc, enc_ctx, 1)
174
175
176# Lookups key in the store. The caller is responsible for destroying
177# returned key with destroy method.
178#
179# Returns key or None if key not found or an error occurs.
180def files_keys_store_find_key(store, name, keyInfoCtx):
181    assert(store)
182    assert(keyInfoCtx)
183
184    ctx = xmlsec.KeyInfoCtx(_obj=keyInfoCtx)
185   
186    import pdb
187    pdb.set_trace()
188   
189    # It's possible to do not have the key name or desired key type
190    # but we could do nothing in this case
191    if name is None or ctx.keyReq.keyId == xmlsec.KeyDataIdUnknown:
192        print "Return None"
193        return None
194   
195    #import pdb
196    #pdb.set_trace()
197    key = xmlsec.cryptoAppKeyLoad(name, xmlsec.KeyDataFormatPem, None, None, None)
198    if key is None:
199        print "Error: failed to load public pem key from \"%s\"" % name
200        return None
201   
202#    if ctx.keyReq.keyId == xmlsec.keyDataDsaId() or ctx.keyReq.keyId == xmlsec.keyDataRsaId():
203        # Load key from a pem file, if key is not found then it's an error (is it?)
204#       key = xmlsec.CryptoAppKeyLoad(name, xmlsec.KeyDataFormatPem, None, None, None)
205#        if key is None:
206#           print "Error: failed to load public pem key from \"%s\"" % name
207#           return None
208#    else:
209#        # Otherwise it's a binary key, if key is not found then it's an error (is it?)
210#        key = xmlsec.keyReadBinaryFile(ctx.keyReq.keyId, name)
211#        if key is None:
212#            print "Error: failed to load key from binary file \"%s\"" % name
213#            return None
214   
215    # Set key name
216    if key.setName(name) < 0:
217        print "Error: failed to set key name for key from \"%s\"" % name
218        key.destroy();
219        return None
220   
221    return key
222
223
224# Creates simple keys manager and load DES keys from files in it.
225# The caller is responsible for destroying returned keys manager using
226# destroy.
227#
228# Returns the newly created keys manager or None if an error occurs.
229def loadPriKey(file):
230    assert(file)
231
232    # Create and initialize keys manager, we use a simple list based
233    # keys manager, implement your own KeysStore klass if you need
234    # something more sophisticated
235    mngr = xmlsec.KeysMngr()
236    if mngr is None:
237        print "Error: failed to create keys manager."
238        return None
239    if xmlsec.cryptoAppDefaultKeysMngrInit(mngr) < 0:
240        print "Error: failed to initialize keys manager."
241        mngr.destroy()
242        return None
243   
244    key = xmlsec.cryptoAppKeyLoad(file, xmlsec.KeyDataFormatPem, None, None, None)
245    if key is None:
246        print "Error: failed to load private key from file \"%s\"" % file
247        mngr.destroy()
248        return None
249   
250    # Add key to keys manager, from now on keys manager is responsible
251    # for destroying key
252    if xmlsec.cryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0:
253        print "Error: failed to add key from \"%s\" to keys manager" % file
254        key.destroy()
255        mngr.destroy()
256        return None
257   
258    return mngr
259
260def cleanup(doc=None, enc_ctx=None, res=-1):
261    if enc_ctx is not None:
262        enc_ctx.destroy()
263    if doc is not None:
264        doc.freeDoc()
265    return res
266
267
268def check_filename(filename):
269    if os.access(filename, os.R_OK):
270        return 1
271    else:
272        print "Error: XML file \"%s\" not found OR no read access" % filename
273        return 0
274
275
276if __name__ == "__main__":
277    main()
Note: See TracBrowser for help on using the repository browser.