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 by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   * 
13   * GoldenGate is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Public License along with
18   * GoldenGate . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package goldengate.common.crypto;
21  
22  /**
23   * This class handles methods to encrypt and unencrypt messages with any available
24   * algorithms in the JVM.<br>
25   * <b>AES is the best compromise in term of security and efficiency.</b>
26   * <br>
27   * Usage:<br>
28   * <ul>
29   * <li>Create a Key object: DynamicKey key = new DynamicKey(size,algo,instance,extension);<br>
30   * As DynamicKey(56, "DES", "DES/ECB/PKCS5Padding", "des") for DES<br>
31   * or through Enum class INSTANCES (minimal supported size) or INSTANCESMAX (maximal supported size) as DynamicKey(INSTANCESMAX.AES,"aes")</li>
32   * <li>Create a key:
33   * <ul>
34   * <li>Generate: key.generateKey();<br>
35   * The method key.getSecretKeyInBytes() allow getting the key in Bytes.</li>
36   * <li>From an external source: key.setSecretKey(arrayOfBytes);</li>
37   * </ul>
38   * </li>
39   * <li>To encrypt a String in a Base64 format: String myStringCrypt =
40   * key.cryptToString(myString);</li>
41   * <li>To unencrypt one string from Base64 format to the original String: String
42   * myStringDecrypt = key.decryptStringInString(myStringCrypte);</li>
43   * </ul>
44   * 
45   * @author frederic bregier
46   * 
47   */
48  public class DynamicKeyObject extends KeyObject {
49      
50      /**
51       * Minimal key size
52       * 
53       * @author Frederic Bregier
54       * 
55       */
56      public enum INSTANCES {
57          AES(128), // Min 128
58          ARCFOUR(56), // No Max
59          Blowfish(56), // No Max
60          DES(56), // Must be 56 except if Strong Policy is used
61          DESede(112), // 112 or 168 triple DES
62          RC2(56),
63          RC4(56);
64  
65          int size;
66  
67          private INSTANCES(int size) {
68              this.size = size;
69          }
70      }
71  
72      /**
73       * Recommended key size when normal JVM installed (no extension on encrypt
74       * support)
75       * 
76       * @author Frederic Bregier
77       * 
78       */
79      public enum INSTANCESMAX {
80          AES(128), // Min 128
81          ARCFOUR(128), // No Max
82          Blowfish(128), // No Max
83          DES(56), // Must be 56 except if Strong Policy is used
84          DESede(168), // 112 or 168 triple DES
85          RC2(128),
86          RC4(128);
87  
88          int size;
89  
90          private INSTANCESMAX(int size) {
91              this.size = size;
92          }
93      }
94  
95      /**
96       * This value could be between 32 and 128 due to license limitation.
97       */
98      public final int KEY_SIZE;
99      /**
100      * Short name for the algorithm
101      */
102     public final String ALGO;
103     /**
104      * Could be the shortname again (default implementation in JVM) or the full name as DES/ECB/PKCS5Padding
105      */
106     public final String INSTANCE;
107     /**
108      * The extension for the file to use when saving the key (note that an extra file as extension.inf will be also saved for the extra information)
109      */
110     public final String EXTENSION;
111 
112     /**
113      * @param kEYSIZE
114      *            example DES: 56
115      * @param aLGO
116      *            example DES: DES
117      * @param iNSTANCE
118      *            example DES: DES/ECB/PKCS5Padding
119      * @param eXTENSION
120      *            example DES: des
121      */
122     public DynamicKeyObject(int kEYSIZE, String aLGO, String iNSTANCE,
123             String eXTENSION) {
124         super();
125         KEY_SIZE = kEYSIZE;
126         ALGO = aLGO;
127         INSTANCE = iNSTANCE;
128         EXTENSION = eXTENSION;
129     }
130     /**
131      * 
132      * @param instance the minimal default instance
133      * @param eXTENSION to use for files
134      */
135     public DynamicKeyObject(INSTANCES instance,
136             String eXTENSION) {
137         super();
138         KEY_SIZE = instance.size;
139         ALGO = instance.name();
140         INSTANCE = instance.name();
141         EXTENSION = eXTENSION;
142     }
143     /**
144      * 
145      * @param instance the maximal default instance
146      * @param eXTENSION to use for files
147      */
148     public DynamicKeyObject(INSTANCESMAX instance,
149             String eXTENSION) {
150         super();
151         KEY_SIZE = instance.size;
152         ALGO = instance.name();
153         INSTANCE = instance.name();
154         EXTENSION = eXTENSION;
155     }
156 
157     /*
158      * (non-Javadoc)
159      * 
160      * @see goldengate.common.crypto.KeyObject#getAlgorithm()
161      */
162     @Override
163     public String getAlgorithm() {
164         return ALGO;
165     }
166 
167     /*
168      * (non-Javadoc)
169      * 
170      * @see goldengate.common.crypto.KeyObject#getInstance()
171      */
172     @Override
173     public String getInstance() {
174         return INSTANCE;
175     }
176 
177     /*
178      * (non-Javadoc)
179      * 
180      * @see goldengate.common.crypto.KeyObject#getKeySize()
181      */
182     @Override
183     public int getKeySize() {
184         return KEY_SIZE;
185     }
186 
187     /**
188      * This method allows to test the correctness of this class
189      * 
190      * @param args
191      * @throws Exception
192      */
193     public static void main(String[] args) throws Exception {
194         String plaintext = null;
195         if (args.length != 0) {
196             plaintext = args[0];
197         }
198         if (plaintext == null || plaintext.length() == 0) {
199             plaintext = "This is a try for a very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long String";
200         }
201         System.out.println("plaintext = " + plaintext);
202         System.out.println("=====================================");
203         // Can implements with KeyGenerator AES, ARCFOUR, Blowfish, DES, DESede,
204         // RC2, RC4
205         for (INSTANCES instance: INSTANCES.values()) {
206             test(plaintext, instance.size, instance.name());
207         }
208         for (INSTANCESMAX instance: INSTANCESMAX.values()) {
209             test(plaintext, instance.size, instance.name());
210         }
211     }
212 
213     /**
214      * test function
215      * 
216      * @param plaintext
217      * @param size
218      * @param algo
219      * @throws Exception
220      */
221     private static void test(String plaintext, int size, String algo)
222             throws Exception {
223         DynamicKeyObject dyn = new DynamicKeyObject(size, algo, algo, algo);
224         // Generate a key
225         dyn.generateKey();
226         // get the generated key
227         byte[] secretKey = dyn.getSecretKeyInBytes();
228         // crypt one text
229         byte[] ciphertext = dyn.crypt(plaintext);
230         // print the cipher
231         //System.out.println("ciphertext = " + dyn.encodeHex(ciphertext));
232 
233         // Test the set Key
234         dyn.setSecretKey(secretKey);
235         // decrypt the cipher
236         String plaintext2 = dyn.decryptInString(ciphertext);
237         // print the result
238         //System.out.println("plaintext2 = " + plaintext2);
239         if (!plaintext2.equals(plaintext))
240             System.out.println("Error: plaintext2 != plaintext");
241 
242         // same on String only
243         int nb = 100000;
244         long time1 = System.currentTimeMillis();
245         for (int i = 0; i < nb; i ++) {
246             String cipherString = dyn.cryptToHex(plaintext);
247             // System.out.println("cipherString = " + cipherString);
248             String plaintext3 = dyn.decryptHexInString(cipherString);
249             // System.out.println("plaintext3 = " + plaintext3);
250             if (!plaintext3.equals(plaintext))
251                 System.out.println("Error: plaintext3 != plaintext");
252         }
253         long time2 = System.currentTimeMillis();
254         System.out.println(algo + ": Total time: " + (time2 - time1) + " ms, " +
255                 (nb * 1000 / (time2 - time1)) + " crypt or decrypt/s");
256     }
257 }