View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.common.crypto;
22  
23  import goldengate.common.digest.FilesystemBasedDigest;
24  import goldengate.common.exception.CryptoException;
25  import goldengate.common.logging.GgInternalLogger;
26  import goldengate.common.logging.GgInternalLoggerFactory;
27  
28  import java.io.DataInputStream;
29  import java.io.File;
30  import java.io.FileInputStream;
31  import java.io.FileOutputStream;
32  import java.io.IOException;
33  import java.security.Key;
34  
35  import javax.crypto.Cipher;
36  import javax.crypto.KeyGenerator;
37  import javax.crypto.spec.SecretKeySpec;
38  
39  
40  /**
41   * This class handles method to crypt and decrypt using the chosen algorithm.<br>
42   *
43   * <br>
44   * Usage:<br>
45   * <ul>
46   * <li>Create a Key object: KeyObject key = new KeyObject();</li>
47   * <li>Create a key:
48   * <ul>
49   * <li>Generate: key.generateKey();<br>
50   * The method key.getSecretKeyInBytes() allow getting the key in Bytes.</li>
51   * <li>From an external source: key.setSecretKey(arrayOfBytes);</li>
52   * </ul></li>
53   * <li>To crypt a String in a Hex format: String myStringCrypt = key.cryptToHex(myString);</li>
54   * <li>To decrypt one string from Hex format to the original String: String myStringDecrypt = key.decryptHexInString(myStringCrypte);</li>
55   * </ul>
56   *
57   * @author frederic bregier
58   *
59   */
60  public abstract class KeyObject {
61      /**
62       * Internal Logger
63       */
64      private static final GgInternalLogger logger = GgInternalLoggerFactory
65              .getLogger(KeyObject.class);
66      
67      /**
68       * The True Key associated with this object
69       */
70      Key secretKey = null;
71  
72      /**
73       * Empty constructor
74       */
75      public KeyObject() {
76      }
77  
78      /**
79       *
80       * @return the algorithm used (Java name)
81       */
82      public abstract String getAlgorithm();
83      /**
84       *
85       * @return the instance used (Java name)
86       */
87      public abstract String getInstance();
88      /**
89       *
90       * @return the size for the algorithm key
91       */
92      public abstract int getKeySize();
93      /**
94       * @return the key associated with this object
95       */
96      public Key getSecretKey() {
97          return secretKey;
98      }
99  
100     /**
101      *
102      * @return True if this key is ready to be used
103      */
104     public boolean keyReady() {
105         return secretKey != null;
106     }
107     /**
108      * Returns the key as an array of bytes in order to be stored somewhere else
109      * and retrieved using the setSecretKey(byte[] keyData) method.
110      * @return the key as an array of bytes (or null if not ready)
111      */
112     public byte[] getSecretKeyInBytes() {
113         if (keyReady()) {
114             return secretKey.getEncoded();
115         } else {
116             return null;
117         }
118     }
119 
120     /**
121      * Set the secretKey
122      *
123      * @param secretKey
124      */
125     public void setSecretKey(Key secretKey) {
126         this.secretKey = secretKey;
127     }
128 
129     /**
130      * Reconstruct a key from an array of bytes
131      */
132     public void setSecretKey(byte[] keyData) {
133         secretKey = new SecretKeySpec(keyData, getAlgorithm());
134     }
135 
136     /**
137      * Create a Key from a File
138      * @param file
139      * @throws CryptoException
140      * @throws IOException
141      */
142     public void setSecretKey(File file) throws CryptoException, IOException {
143         if (file.canRead()) {
144             int len = (int)file.length();
145             byte []key = new byte[len];
146             FileInputStream inputStream = null;
147             inputStream = new FileInputStream(file);
148             DataInputStream dis = new DataInputStream(inputStream);
149             try {
150             	dis.readFully(key);
151             } finally {
152             	dis.close();
153             }
154             this.setSecretKey(key);
155         } else {
156             throw new CryptoException("Cannot read crypto file");
157         }
158     }
159     /**
160      * Save a Key to a File
161      * @param file
162      * @throws CryptoException
163      * @throws IOException
164      */
165     public void saveSecretKey(File file) throws CryptoException, IOException {
166         if (keyReady() && ((!file.exists()) || file.canWrite())) {
167             byte []key = getSecretKeyInBytes();
168             FileOutputStream outputStream = new FileOutputStream(file);
169             try {
170 	            outputStream.write(key);
171 	            outputStream.flush();
172             } finally {
173             	outputStream.close();
174             }
175         } else {
176             throw new CryptoException("Cannot read crypto file");
177         }
178     }
179 
180     /**
181      * Generate a key from nothing
182      * @throws Exception
183      */
184     public void generateKey() throws Exception {
185         try {
186             KeyGenerator keyGen = KeyGenerator.getInstance(getAlgorithm());
187             keyGen.init(getKeySize());
188             secretKey = keyGen.generateKey();
189         } catch (Exception e) {
190             logger.warn("GenerateKey Error", e);
191             throw e;
192         }
193     }
194     /**
195      * Returns a cipher for encryption associated with the key
196      * 
197      * @return the cipher for encryption or null if it fails
198      * in case Encryption method or key is incorrect
199      */
200     public Cipher toCrypt() {
201         Cipher cipher;
202         try {
203             cipher = Cipher.getInstance(getInstance());
204             cipher.init(Cipher.ENCRYPT_MODE, secretKey);
205         } catch (Exception e) {
206             return null;
207         }
208         return cipher;
209     }
210     /**
211      * Crypt one array of bytes and returns the crypted array of bytes
212      *
213      * @param plaintext
214      * @return the crypted array of bytes
215      * @throws Exception
216      */
217     public byte[] crypt(byte[] plaintext) throws Exception {
218         if (! keyReady()) {
219             throw new CryptoException("Key not Ready");
220         }
221         try {
222             Cipher cipher = Cipher.getInstance(getInstance());
223             cipher.init(Cipher.ENCRYPT_MODE, secretKey);
224             return cipher.doFinal(plaintext);
225         } catch (Exception e) {
226             logger.warn("Crypt Error", e);
227             throw e;
228         }
229     }
230 
231     /**
232      * Crypt one array of bytes and returns the crypted String as HEX format
233      *
234      * @param plaintext
235      * @return the crypted String as HEX format
236      * @throws Exception
237      */
238     public String cryptToHex(byte[] plaintext) throws Exception {
239         byte []result = crypt(plaintext);
240         return encodeHex(result);
241     }
242 
243     /**
244      * Crypt one String and returns the crypted array of bytes
245      *
246      * @param plaintext
247      * @return the crypted array of bytes
248      * @throws Exception
249      */
250     public byte[] crypt(String plaintext) throws Exception {
251         return crypt(plaintext.getBytes());
252     }
253 
254     /**
255      * Crypt one String and returns the crypted String as HEX format
256      *
257      * @param plaintext
258      * @return the crypted String as HEX format
259      * @throws Exception
260      */
261     public String cryptToHex(String plaintext) throws Exception {
262         return cryptToHex(plaintext.getBytes());
263     }
264     /**
265      * Returns a cipher for decryption associated with the key
266      * 
267      * @return the cipher for decryption or null if it fails
268      * in case Encryption method or key is incorrect
269      */
270     public Cipher toDecrypt() {
271         Cipher cipher;
272         try {
273             cipher = Cipher.getInstance(getAlgorithm());
274             cipher.init(Cipher.DECRYPT_MODE, secretKey);
275         } catch (Exception e) {
276             return null;
277         }
278         return cipher;
279     }
280     /**
281      * Decrypt an array of bytes and returns the uncrypted array of bytes
282      *
283      * @param ciphertext
284      * @return the uncrypted array of bytes
285      * @throws Exception
286      */
287     public byte[] decrypt(byte[] ciphertext) throws Exception {
288         if (! keyReady()) {
289             throw new CryptoException("Key not Ready");
290         }
291         try {
292             Cipher cipher = Cipher.getInstance(getAlgorithm());
293             cipher.init(Cipher.DECRYPT_MODE, secretKey);
294             return cipher.doFinal(ciphertext);
295         } catch (Exception e) {
296             logger.warn("Decrypt Error", e);
297             throw e;
298         }
299     }
300 
301     /**
302      * Decrypt an array of bytes and returns the uncrypted String
303      *
304      * @param ciphertext
305      * @return the uncrypted array of bytes
306      * @throws Exception
307      */
308     public String decryptInString(byte[] ciphertext) throws Exception {
309         return new String(decrypt(ciphertext));
310     }
311 
312     /**
313      * Decrypt a String as HEX format representing a crypted array of bytes and
314      * returns the uncrypted array of bytes
315      *
316      * @param ciphertext
317      * @return the uncrypted array of bytes
318      * @throws Exception
319      */
320     public byte[] decryptHexInBytes(String ciphertext) throws Exception {
321         byte[] arrayBytes = decodeHex(ciphertext);
322         return decrypt(arrayBytes);
323     }
324     /**
325      * Decrypt an array of bytes as HEX format representing a crypted array of bytes and
326      * returns the uncrypted array of bytes
327      *
328      * @param ciphertext
329      * @return the uncrypted array of bytes
330      * @throws Exception
331      */
332     public byte[] decryptHexInBytes(byte[] ciphertext) throws Exception {
333         byte[] arrayBytes = decodeHex(new String(ciphertext));
334         return decrypt(arrayBytes);
335     }
336     /**
337      * Decrypt a String as HEX format representing a crypted array of bytes and
338      * returns the uncrypted String
339      *
340      * @param ciphertext
341      * @return the uncrypted String
342      * @throws Exception
343      */
344     public String decryptHexInString(String ciphertext) throws Exception {
345         return new String(decryptHexInBytes(ciphertext));
346     }
347 
348     /**
349      * Decode from a file containing a HEX crypted string
350      * @param file
351      * @return the decoded uncrypted content of the file
352      * @throws Exception
353      */
354     public byte[] decryptHexFile(File file) throws Exception {
355         byte [] byteKeys = new byte[(int) file.length()];
356         FileInputStream inputStream = null;
357         DataInputStream dis = null;
358         try {
359             inputStream = new FileInputStream(file);
360             dis = new DataInputStream(inputStream);
361             dis.readFully(byteKeys);
362             dis.close();
363             String skey = new String(byteKeys);
364             // decrypt it
365             byteKeys = decryptHexInBytes(skey);
366             return byteKeys;
367         } catch (IOException e) {
368             try {
369                 if (dis != null) {
370                     dis.close();
371                 } else if (inputStream != null)
372                     inputStream.close();
373             } catch (IOException e1) {
374             }
375             throw e;
376         }
377     }
378 
379     /**
380     *
381     * @param encoded
382     * @return the array of bytes from encoded String (HEX)
383     */
384    public byte[] decodeHex(String encoded) {
385        return FilesystemBasedDigest.getFromHex(encoded);
386    }
387 
388     /**
389      *
390      * @param bytes
391      * @return The encoded array of bytes in HEX
392      */
393     public String encodeHex(byte[] bytes) {
394         return FilesystemBasedDigest.getHex(bytes);
395     }
396 }