1 package org.apache.fulcrum.jce.crypto; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import java.io.ByteArrayOutputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.io.OutputStream; 26 import java.security.GeneralSecurityException; 27 28 import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8; 29 import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template; 30 import org.apache.fulcrum.jce.crypto.extended.CryptoUtilJ8; 31 32 /** 33 * Helper class to provde generic functions to work with CryptoStreams. 34 * 35 * The code uses parts from Markus Hahn's Blowfish library found at 36 * http://blowfishj.sourceforge.net/ 37 * 38 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl </a> 39 * @author <a href="mailto:maakus@earthlink.net">Markus Hahn</a> 40 */ 41 42 public class CryptoUtil { 43 44 /** the default instance */ 45 private static CryptoUtil instance; 46 47 48 protected CryptoStreamFactory cryptoStreamFactory; 49 50 /** 51 * Factory method to get a default instance 52 * 53 * @return an instance of the CryptoUtil 54 */ 55 public synchronized static CryptoUtil getInstance() { 56 if (CryptoUtil.instance == null) { 57 CryptoUtil.instance = new CryptoUtil(); 58 } 59 60 return CryptoUtil.instance; 61 } 62 63 /** 64 * 65 */ 66 protected CryptoUtil() { 67 cryptoStreamFactory = CryptoStreamFactoryImpl.getInstance(); 68 } 69 70 /** 71 * Factory method to get a default instance 72 * 73 * @param salt the salt for the PBE algorithm 74 * @param count the iteration for PBEParameterSpec 75 * @return an instance of the CryptoUtil 76 */ 77 public synchronized static CryptoUtil getInstance(byte[] salt, int count) { 78 if (CryptoUtil.instance == null) { 79 CryptoUtil.instance = new CryptoUtil(salt, count); 80 } 81 82 return CryptoUtil.instance; 83 } 84 85 /** 86 * @param salt the salt for the PBE algorithm 87 * @param count the iteration for PBEParameterSpec 88 */ 89 protected CryptoUtil(byte[] salt, int count) { 90 cryptoStreamFactory = CryptoStreamFactoryImpl.getInstance(salt, count); 91 } 92 93 /** 94 * Copies from a source to a target object using encryption 95 * 96 * @param source the source object 97 * @param target the target object 98 * @param password the password to use for encryption 99 * @throws GeneralSecurityException accessing JCE failed 100 * @throws IOException accessing the souce failed 101 * 102 */ 103 public void encrypt(Object source, Object target, char[] password) throws GeneralSecurityException, IOException { 104 encrypt(getCryptoStreamFactory(), source, target, password); 105 } 106 107 /** 108 * Copies from a source to a target object using encryption and a caller 109 * supplied CryptoStreamFactory. 110 * 111 * @param factory the factory to create the crypto streams 112 * @param source the source object 113 * @param target the target object 114 * @param password the password to use for encryption 115 * @throws GeneralSecurityException accessing JCE failed 116 * @throws IOException accessing the souce failed 117 */ 118 public void encrypt(CryptoStreamFactory factory, Object source, Object target, char[] password) 119 throws GeneralSecurityException, IOException { 120 InputStream is = StreamUtil.createInputStream(source); 121 OutputStream os = StreamUtil.createOutputStream(target); 122 OutputStream eos = factory.getOutputStream(os, password); 123 StreamUtil.copy(is, eos); 124 } 125 126 127 /** 128 * Encrypts a string into a hex string using {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT} 129 * 130 * @param plainText the plain text to be encrypted 131 * @param password the password for encryption 132 * @return the encrypted string 133 * @throws GeneralSecurityException accessing JCE failed 134 * @throws IOException accessing the souce failed 135 */ 136 public String encryptStringWithClearCode(String plainText, char[] password) throws GeneralSecurityException, IOException { 137 return encryptString(getCryptoStreamFactory(), plainText, password, true); 138 } 139 140 /** 141 * Encrypts a string into a hex string. 142 * 143 * @param plainText the plain text to be encrypted 144 * @param password the password for encryption 145 * @return the encrypted string 146 * @throws GeneralSecurityException accessing JCE failed 147 * @throws IOException accessing the souce failed 148 */ 149 public String encryptString(String plainText, char[] password) throws GeneralSecurityException, IOException { 150 return encryptString(getCryptoStreamFactory(), plainText, password, false); 151 } 152 153 /** 154 * Encrypts a string into a hex string. 155 * 156 * @param factory the factory to create the crypto streams 157 * @param plainText the plain text to be encrypted 158 * @param password the password for encryption 159 * @param withClearCode boolean to indicate, that a string containing how it was decoded is included 160 * @return the encrypted string 161 * @throws GeneralSecurityException accessing JCE failed 162 * @throws IOException accessing the souce failed 163 */ 164 public String encryptString(CryptoStreamFactory factory, String plainText, char[] password, boolean withClearCode) 165 throws GeneralSecurityException, IOException { 166 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 167 encrypt(factory, plainText, baos, password); 168 String prefix = (withClearCode)? (this instanceof CryptoUtilJ8)? 169 ((CryptoStreamFactoryJ8Template)((CryptoUtilJ8)this).getCryptoStreamFactory()).getType().getClearCode() 170 : CryptoParametersJ8.CLEAR_CODE_DEFAULT: ""; 171 return prefix + HexConverter.toString(baos.toByteArray()); 172 } 173 174 /** 175 * Copies from a source to a target object using decryption. 176 * 177 * @param source the source object 178 * @param target the target object 179 * @param password the password to use for decryption 180 * @throws GeneralSecurityException accessing JCE failed 181 * @throws IOException accessing the souce failed 182 */ 183 public void decrypt(Object source, Object target, char[] password) throws GeneralSecurityException, IOException { 184 decrypt(getCryptoStreamFactory(), source, target, password); 185 } 186 187 /** 188 * Decrypts an encrypted string into the plain text. The encrypted string must 189 * be a hex string created by encryptString. 190 * 191 * Decrypts encrypted text after {@link CryptoParametersJ8#CLEAR_CODE_DEFAULT}. 192 * 193 * Removes ClearCode length of 10 bit, before decrpyting expected as prefix. 194 * 195 * @param cipherText the encrypted text to be decrypted 196 * @param password the password for decryption 197 * @return the decrypted string 198 * @throws GeneralSecurityException accessing JCE failed 199 * @throws IOException accessing the souce failed 200 */ 201 public String decryptStringWithClearCode(String cipherText, char[] password) throws GeneralSecurityException, IOException { 202 return decryptString(getCryptoStreamFactory(), cipherText.substring(10), password); 203 } 204 205 /** 206 * Decrypts an encrypted string into the plain text. The encrypted string must 207 * be a hex string created by encryptString. 208 * 209 * @param cipherText the encrypted text to be decrypted 210 * @param password the password for decryption 211 * @return the decrypted string 212 * @throws GeneralSecurityException accessing JCE failed 213 * @throws IOException accessing the souce failed 214 */ 215 public String decryptString(String cipherText, char[] password) throws GeneralSecurityException, IOException { 216 return decryptString(getCryptoStreamFactory(), cipherText, password); 217 } 218 219 /** 220 * Decrypts an encrypted string into the plain text. The encrypted string must 221 * be a hex string created by encryptString. 222 * 223 * @param cipherText the encrypted text to be decrypted 224 * @param password the password for decryption 225 * @param withClearCode boolean to indicate, that a string containing how it was decoded was included during encryption 226 * @return the decrypted string 227 * @throws GeneralSecurityException accessing JCE failed 228 * @throws IOException accessing the souce failed 229 */ 230 public String decryptString(String cipherText, char[] password, boolean withClearCode) throws GeneralSecurityException, IOException { 231 return decryptString(getCryptoStreamFactory(), withClearCode? 232 cipherText.substring(CryptoParametersJ8.CLEAR_CODE_DEFAULT.length()): 233 cipherText, password); 234 } 235 236 /** 237 * Copies from a source to a target object using decryption and a caller-suppier 238 * CryptoStreamFactory. 239 * 240 * @param factory the factory to create the crypto streams 241 * @param source the source object 242 * @param target the target object 243 * @param password the password to use for decryption 244 * @throws GeneralSecurityException accessing JCE failed 245 * @throws IOException accessing the souce failed 246 */ 247 protected void decrypt(CryptoStreamFactory factory, Object source, Object target, char[] password) 248 throws GeneralSecurityException, IOException { 249 InputStream is = StreamUtil.createInputStream(source); 250 OutputStream os = StreamUtil.createOutputStream(target); 251 InputStream dis = factory.getInputStream(is, password); 252 StreamUtil.copy(dis, os); 253 } 254 255 /** 256 * Decrypts an encrypted string into the plain text. The encrypted string must 257 * be a hex string created by encryptString. 258 * 259 * @param factory the factory to create the crypto streams 260 * @param cipherText the encrypted text to be decrypted 261 * @param password the password for decryption 262 * @return the decrypted string 263 * @throws GeneralSecurityException accessing JCE failed 264 * @throws IOException accessing the souce failed 265 */ 266 public String decryptString(CryptoStreamFactory factory, String cipherText, char[] password) 267 throws GeneralSecurityException, IOException { 268 byte[] buffer = HexConverter.toBytes(cipherText); 269 ByteArrayOutputStream bais = new ByteArrayOutputStream(); 270 decrypt(factory, buffer, bais, password); 271 return new String(bais.toByteArray(), "utf-8"); 272 } 273 274 /** 275 * Pumps the input stream to the output stream. 276 * 277 * @param is the source input stream 278 * @param os the target output stream 279 * @return the number of bytes copied 280 * @throws IOException the copying failed 281 * @deprecated use StreamUtil instead 282 */ 283 public static long copy(InputStream is, OutputStream os) throws IOException { 284 return StreamUtil.copy(is, os); 285 } 286 287 /** 288 * @return the CryptoStreamFactory to be used 289 */ 290 public CryptoStreamFactory getCryptoStreamFactory() { 291 return cryptoStreamFactory; 292 } 293 294 }