View Javadoc
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 }