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 }