1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 package org.apache.xml.security.samples.encryption;
20 
21 import java.io.File;
22 import java.io.FileOutputStream;
23 
24 import java.security.Key;
25 
26 import javax.crypto.SecretKey;
27 import javax.crypto.KeyGenerator;
28 
29 import org.apache.xml.security.keys.KeyInfo;
30 import org.apache.xml.security.encryption.XMLCipher;
31 import org.apache.xml.security.encryption.EncryptedData;
32 import org.apache.xml.security.encryption.EncryptedKey;
33 import org.apache.xml.security.utils.Constants;
34 
35 import org.w3c.dom.Document;
36 import org.w3c.dom.Element;
37 
38 import javax.xml.transform.TransformerFactory;
39 import javax.xml.transform.Transformer;
40 import javax.xml.transform.dom.DOMSource;
41 import javax.xml.transform.stream.StreamResult;
42 import javax.xml.transform.OutputKeys;
43 
44 /**
45  * This sample demonstrates how to encrypt data inside an xml document.
46  *
47  * @author Vishal Mahajan (Sun Microsystems)
48  */
49 public class Encrypter {
50 
51     /** {@link org.apache.commons.logging} logging facility */
52     static org.apache.commons.logging.Log log =
53         org.apache.commons.logging.LogFactory.getLog(
54             Encrypter.class.getName());
55 
56     static {
org.apache.xml.security.Init.init()57         org.apache.xml.security.Init.init();
58     }
59 
createSampleDocument()60     private static Document createSampleDocument() throws Exception {
61 
62         javax.xml.parsers.DocumentBuilderFactory dbf =
63             javax.xml.parsers.DocumentBuilderFactory.newInstance();
64         dbf.setNamespaceAware(true);
65         javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
66         Document document = db.newDocument();
67 
68         /**
69          * Build a sample document. It will look something like:
70          *
71          * <apache:RootElement xmlns:apache="http://www.apache.org/ns/#app1">
72          * <apache:foo>Some simple text</apache:foo>
73          * </apache:RootElement>
74          */
75         Element root =
76             document.createElementNS("http://www.apache.org/ns/#app1", "apache:RootElement");
77         root.setAttributeNS(
78             Constants.NamespaceSpecNS, "xmlns:apache", "http://www.apache.org/ns/#app1"
79         );
80         document.appendChild(root);
81 
82         root.appendChild(document.createTextNode("\n"));
83 
84         Element childElement =
85             document.createElementNS("http://www.apache.org/ns/#app1", "apache:foo");
86         childElement.appendChild(
87             document.createTextNode("Some simple text"));
88         root.appendChild(childElement);
89 
90         root.appendChild(document.createTextNode("\n"));
91 
92         return document;
93     }
94 
GenerateAndStoreKeyEncryptionKey()95     private static SecretKey GenerateAndStoreKeyEncryptionKey() throws Exception {
96         String jceAlgorithmName = "DESede";
97         KeyGenerator keyGenerator =
98             KeyGenerator.getInstance(jceAlgorithmName);
99         SecretKey kek = keyGenerator.generateKey();
100 
101         byte[] keyBytes = kek.getEncoded();
102         File kekFile = new File("build/kek");
103         FileOutputStream f = new FileOutputStream(kekFile);
104         f.write(keyBytes);
105         f.close();
106         System.out.println("Key encryption key stored in " + kekFile.toURI().toURL().toString());
107 
108         return kek;
109     }
110 
GenerateDataEncryptionKey()111     private static SecretKey GenerateDataEncryptionKey() throws Exception {
112         String jceAlgorithmName = "AES";
113         KeyGenerator keyGenerator =
114             KeyGenerator.getInstance(jceAlgorithmName);
115         keyGenerator.init(128);
116         return keyGenerator.generateKey();
117     }
118 
outputDocToFile(Document doc, String fileName)119     private static void outputDocToFile(Document doc, String fileName) throws Exception {
120         File encryptionFile = new File(fileName);
121         FileOutputStream f = new FileOutputStream(encryptionFile);
122 
123         TransformerFactory factory = TransformerFactory.newInstance();
124         Transformer transformer = factory.newTransformer();
125         transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
126         DOMSource source = new DOMSource(doc);
127         StreamResult result = new StreamResult(f);
128         transformer.transform(source, result);
129 
130         f.close();
131         System.out.println(
132             "Wrote document containing encrypted data to " + encryptionFile.toURI().toURL().toString()
133         );
134     }
135 
main(String unused[])136     public static void main(String unused[]) throws Exception {
137 
138         Document document = createSampleDocument();
139 
140         /*
141          * Get a key to be used for encrypting the element.
142          * Here we are generating an AES key.
143          */
144         Key symmetricKey = GenerateDataEncryptionKey();
145 
146         /*
147          * Get a key to be used for encrypting the symmetric key.
148          * Here we are generating a DESede key.
149          */
150         Key kek = GenerateAndStoreKeyEncryptionKey();
151 
152         String algorithmURI = XMLCipher.TRIPLEDES_KeyWrap;
153 
154         XMLCipher keyCipher =
155             XMLCipher.getInstance(algorithmURI);
156         keyCipher.init(XMLCipher.WRAP_MODE, kek);
157         EncryptedKey encryptedKey =
158             keyCipher.encryptKey(document, symmetricKey);
159 
160         /*
161          * Let us encrypt the contents of the document element.
162          */
163         Element rootElement = document.getDocumentElement();
164 
165         algorithmURI = XMLCipher.AES_128;
166 
167         XMLCipher xmlCipher =
168             XMLCipher.getInstance(algorithmURI);
169         xmlCipher.init(XMLCipher.ENCRYPT_MODE, symmetricKey);
170 
171         /*
172          * Setting keyinfo inside the encrypted data being prepared.
173          */
174         EncryptedData encryptedData = xmlCipher.getEncryptedData();
175         KeyInfo keyInfo = new KeyInfo(document);
176         keyInfo.add(encryptedKey);
177         encryptedData.setKeyInfo(keyInfo);
178 
179         /*
180          * doFinal -
181          * "true" below indicates that we want to encrypt element's content
182          * and not the element itself. Also, the doFinal method would
183          * modify the document by replacing the EncrypteData element
184          * for the data to be encrypted.
185          */
186         xmlCipher.doFinal(document, rootElement, true);
187 
188         /*
189          * Output the document containing the encrypted information into
190          * a file.
191          */
192         outputDocToFile(document, "build/encryptedInfo.xml");
193     }
194 }
195