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