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 }