Git init
[external/xmlsec1.git] / examples / decrypt2.c
1 /** 
2  * XML Security Library example: Decrypting an encrypted file using keys manager.
3  * 
4  * Decrypts encrypted XML file using keys manager and a list of 
5  * DES key from a binary file
6  * 
7  * Usage: 
8  *      ./decrypt2 <xml-enc> <des-key-file1> [<des-key-file2> [...]] 
9  *
10  * Example:
11  *      ./decrypt2 encrypt1-res.xml deskey.bin
12  *      ./decrypt2 encrypt2-res.xml deskey.bin
13  *
14  * This is free software; see Copyright file in the source
15  * distribution for preciese wording.
16  * 
17  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
18  */
19 #include <stdlib.h>
20 #include <string.h>
21 #include <assert.h>
22
23 #include <libxml/tree.h>
24 #include <libxml/xmlmemory.h>
25 #include <libxml/parser.h>
26
27 #ifndef XMLSEC_NO_XSLT
28 #include <libxslt/xslt.h>
29 #endif /* XMLSEC_NO_XSLT */
30
31 #include <xmlsec/xmlsec.h>
32 #include <xmlsec/xmltree.h>
33 #include <xmlsec/xmlenc.h>
34 #include <xmlsec/crypto.h>
35
36 xmlSecKeysMngrPtr load_des_keys(char** files, int files_size);
37 int decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file);
38
39 int 
40 main(int argc, char **argv) {
41     xmlSecKeysMngrPtr mngr;
42
43     assert(argv);
44
45     if(argc != 3) {
46         fprintf(stderr, "Error: wrong number of arguments.\n");
47         fprintf(stderr, "Usage: %s <enc-file> <key-file1> [<key-file2> [...]]\n", argv[0]);
48         return(1);
49     }
50
51     /* Init libxml and libxslt libraries */
52     xmlInitParser();
53     LIBXML_TEST_VERSION
54     xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
55     xmlSubstituteEntitiesDefault(1);
56 #ifndef XMLSEC_NO_XSLT
57     xmlIndentTreeOutput = 1; 
58 #endif /* XMLSEC_NO_XSLT */
59                 
60     /* Init xmlsec library */
61     if(xmlSecInit() < 0) {
62         fprintf(stderr, "Error: xmlsec initialization failed.\n");
63         return(-1);
64     }
65
66     /* Check loaded library version */
67     if(xmlSecCheckVersion() != 1) {
68         fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
69         return(-1);
70     }
71
72     /* Load default crypto engine if we are supporting dynamic
73      * loading for xmlsec-crypto libraries. Use the crypto library
74      * name ("openssl", "nss", etc.) to load corresponding 
75      * xmlsec-crypto library.
76      */
77 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
78     if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
79         fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
80                         "that you have it installed and check shared libraries path\n"
81                         "(LD_LIBRARY_PATH) envornment variable.\n");
82         return(-1);     
83     }
84 #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
85
86     /* Init crypto library */
87     if(xmlSecCryptoAppInit(NULL) < 0) {
88         fprintf(stderr, "Error: crypto initialization failed.\n");
89         return(-1);
90     }
91
92     /* Init xmlsec-crypto library */
93     if(xmlSecCryptoInit() < 0) {
94         fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
95         return(-1);
96     }
97
98     /* create keys manager and load keys */
99     mngr = load_des_keys(&(argv[2]), argc - 2);
100     if(mngr == NULL) {
101         return(-1);
102     }
103
104     if(decrypt_file(mngr, argv[1]) < 0) {
105         xmlSecKeysMngrDestroy(mngr);    
106         return(-1);
107     }    
108
109     /* destroy keys manager */
110     xmlSecKeysMngrDestroy(mngr);
111     
112     /* Shutdown xmlsec-crypto library */
113     xmlSecCryptoShutdown();
114     
115     /* Shutdown crypto library */
116     xmlSecCryptoAppShutdown();
117     
118     /* Shutdown xmlsec library */
119     xmlSecShutdown();
120
121     /* Shutdown libxslt/libxml */
122 #ifndef XMLSEC_NO_XSLT
123     xsltCleanupGlobals();            
124 #endif /* XMLSEC_NO_XSLT */
125     xmlCleanupParser();
126     
127     return(0);
128 }
129
130 /**
131  * load_des_keys:
132  * @files:              the list of filenames.
133  * @files_size:         the number of filenames in #files.
134  *
135  * Creates simple keys manager and load DES keys from #files in it.
136  * The caller is responsible for destroing returned keys manager using
137  * @xmlSecKeysMngrDestroy.
138  *
139  * Returns the pointer to newly created keys manager or NULL if an error
140  * occurs.
141  */
142 xmlSecKeysMngrPtr 
143 load_des_keys(char** files, int files_size) {
144     xmlSecKeysMngrPtr mngr;
145     xmlSecKeyPtr key;
146     int i;
147     
148     assert(files);
149     assert(files_size > 0);
150     
151     /* create and initialize keys manager, we use a simple list based
152      * keys manager, implement your own xmlSecKeysStore klass if you need
153      * something more sophisticated 
154      */
155     mngr = xmlSecKeysMngrCreate();
156     if(mngr == NULL) {
157         fprintf(stderr, "Error: failed to create keys manager.\n");
158         return(NULL);
159     }
160     if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
161         fprintf(stderr, "Error: failed to initialize keys manager.\n");
162         xmlSecKeysMngrDestroy(mngr);
163         return(NULL);
164     }    
165     
166     for(i = 0; i < files_size; ++i) {
167         assert(files[i]);
168
169         /* load DES key */
170         key = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, files[i]);
171         if(key == NULL) {
172             fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", files[i]);
173             xmlSecKeysMngrDestroy(mngr);
174             return(NULL);
175         }
176
177         /* set key name to the file name, this is just an example! */
178         if(xmlSecKeySetName(key, BAD_CAST files[i]) < 0) {
179             fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", files[i]);
180             xmlSecKeyDestroy(key);
181             xmlSecKeysMngrDestroy(mngr);
182             return(NULL);
183         }
184         
185         /* add key to keys manager, from now on keys manager is responsible 
186          * for destroying key 
187          */
188         if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
189             fprintf(stderr,"Error: failed to add key from \"%s\" to keys manager\n", files[i]);
190             xmlSecKeyDestroy(key);
191             xmlSecKeysMngrDestroy(mngr);
192             return(NULL);
193         }
194     }
195
196     return(mngr);
197 }
198
199 /**
200  * decrypt_file:
201  * @mngr:               the pointer to keys manager.
202  * @enc_file:           the encrypted XML  file name.
203  *
204  * Decrypts the XML file #enc_file using DES key from #key_file and 
205  * prints results to stdout.
206  *
207  * Returns 0 on success or a negative value if an error occurs.
208  */
209 int 
210 decrypt_file(xmlSecKeysMngrPtr mngr, const char* enc_file) {
211     xmlDocPtr doc = NULL;
212     xmlNodePtr node = NULL;
213     xmlSecEncCtxPtr encCtx = NULL;
214     int res = -1;
215     
216     assert(mngr);
217     assert(enc_file);
218
219     /* load template */
220     doc = xmlParseFile(enc_file);
221     if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
222         fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
223         goto done;      
224     }
225     
226     /* find start node */
227     node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
228     if(node == NULL) {
229         fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
230         goto done;      
231     }
232
233     /* create encryption context */
234     encCtx = xmlSecEncCtxCreate(mngr);
235     if(encCtx == NULL) {
236         fprintf(stderr,"Error: failed to create encryption context\n");
237         goto done;
238     }
239
240     /* decrypt the data */
241     if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
242         fprintf(stderr,"Error: decryption failed\n");
243         goto done;
244     }
245         
246     /* print decrypted data to stdout */
247     if(encCtx->resultReplaced != 0) {
248         fprintf(stdout, "Decrypted XML data:\n");
249         xmlDocDump(stdout, doc);
250     } else {
251         fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
252         if(xmlSecBufferGetData(encCtx->result) != NULL) {
253             fwrite(xmlSecBufferGetData(encCtx->result), 
254                   1, 
255                   xmlSecBufferGetSize(encCtx->result),
256                   stdout);
257         }
258     }
259     fprintf(stdout, "\n");
260         
261     /* success */
262     res = 0;
263
264 done:    
265     /* cleanup */
266     if(encCtx != NULL) {
267         xmlSecEncCtxDestroy(encCtx);
268     }
269     
270     if(doc != NULL) {
271         xmlFreeDoc(doc); 
272     }
273     return(res);
274 }
275