CryptUtils: jdoc and code should agree
[nikiroo-utils.git] / src / be / nikiroo / utils / CryptUtils.java
CommitLineData
52e0732e
NR
1package be.nikiroo.utils;
2
3import java.io.IOException;
9fb03c36 4import java.io.UnsupportedEncodingException;
52e0732e
NR
5import java.security.InvalidKeyException;
6import java.security.NoSuchAlgorithmException;
7
8import javax.crypto.BadPaddingException;
9import javax.crypto.Cipher;
10import javax.crypto.IllegalBlockSizeException;
11import javax.crypto.NoSuchPaddingException;
12import javax.crypto.SecretKey;
13import javax.crypto.spec.SecretKeySpec;
9fb03c36 14import javax.net.ssl.SSLException;
52e0732e
NR
15
16/**
17 * Small utility class to do AES encryption/decryption.
18 * <p>
19 * Do not assume it is actually secure until you checked the code...
20 *
21 * @author niki
22 */
23public class CryptUtils {
24 private Cipher ecipher;
25 private Cipher dcipher;
26
27 /**
28 * Small and leazy way to initialize a 128 bits key with {@link CryptUtils}.
29 * <p>
30 * <b>Some</b> part of the key will be used to generate a 128 bits key and
31 * initialize the {@link CryptUtils}; even NULL will generate something.
32 * <p>
33 * <b>This is most probably not secure. Do not use if you actually care
34 * about security.</b>
35 *
36 * @param key
37 * the {@link String} to use as a base for the key, can be NULL
38 */
39 public CryptUtils(String key) {
40 try {
41 init(key2key(key));
42 } catch (InvalidKeyException e) {
43 // We made sure that the key is correct, so nothing here
44 e.printStackTrace();
45 }
46 }
47
48 /**
49 * Create a new instance of {@link CryptUtils} with the given 128 bytes key.
50 * <p>
51 * The key <b>must</b> be exactly 128 bytes long.
52 *
53 * @param bytes32
54 * the 128 bits (32 bytes) of the key
55 *
56 * @throws InvalidKeyException
57 * if the key is not an array of 128 bytes
58 */
59 public CryptUtils(byte[] bytes32) throws InvalidKeyException {
60 init(bytes32);
61 }
62
63 /**
64 * This method required an array of 128 bytes.
65 *
66 * @param bytes32
67 * the array, which <b>must</b> be of 128 bits (32 bytes)
68 *
69 * @throws InvalidKeyException
70 * if the key is not an array of 128 bits (32 bytes)
71 */
72 private void init(byte[] bytes32) throws InvalidKeyException {
73 if (bytes32 == null || bytes32.length != 32) {
74 throw new InvalidKeyException(
75 "The size of the key must be of 128 bits (32 bytes), it is: "
76 + (bytes32 == null ? "null" : "" + bytes32.length)
77 + " bytes");
78 }
79
80 SecretKey key = new SecretKeySpec(bytes32, "AES");
81 try {
82 ecipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
83 dcipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
84 ecipher.init(Cipher.ENCRYPT_MODE, key);
85 dcipher.init(Cipher.DECRYPT_MODE, key);
86 } catch (NoSuchAlgorithmException e) {
87 // Every implementation of the Java platform is required to support
88 // this standard Cipher transformation with 128 bits keys
89 e.printStackTrace();
90 } catch (NoSuchPaddingException e) {
91 // Every implementation of the Java platform is required to support
92 // this standard Cipher transformation with 128 bits keys
93 e.printStackTrace();
94 } catch (InvalidKeyException e) {
95 // Every implementation of the Java platform is required to support
96 // this standard Cipher transformation with 128 bits keys
97 e.printStackTrace();
98 }
99 }
100
101 /**
102 * Encrypt the data.
103 *
104 * @param data
105 * the data to encrypt
106 *
107 * @return the encrypted data
108 *
9fb03c36 109 * @throws SSLException
52e0732e
NR
110 * in case of I/O error (i.e., the data is not what you assumed
111 * it was)
112 */
9fb03c36 113 public byte[] encrypt(byte[] data) throws SSLException {
52e0732e
NR
114 try {
115 return ecipher.doFinal(data);
116 } catch (IllegalBlockSizeException e) {
9fb03c36 117 throw new SSLException(e);
52e0732e 118 } catch (BadPaddingException e) {
9fb03c36 119 throw new SSLException(e);
52e0732e
NR
120 }
121 }
122
123 /**
124 * Encrypt the data.
125 *
126 * @param data
127 * the data to encrypt
128 *
129 * @return the encrypted data
130 *
9fb03c36 131 * @throws SSLException
52e0732e
NR
132 * in case of I/O error (i.e., the data is not what you assumed
133 * it was)
134 */
9fb03c36
NR
135 public byte[] encrypt(String data) throws SSLException {
136 try {
137 return encrypt(data.getBytes("UTF8"));
138 } catch (UnsupportedEncodingException e) {
139 // UTF-8 is required in all confirm JVMs
140 e.printStackTrace();
141 return null;
142 }
52e0732e
NR
143 }
144
145 /**
146 * Encrypt the data, then encode it into Base64.
147 *
148 * @param data
149 * the data to encrypt
150 * @param zip
151 * TRUE to also compress the data in GZIP format; remember that
152 * compressed and not-compressed content are different; you need
153 * to know which is which when decoding
154 *
155 * @return the encrypted data, encoded in Base64
156 *
9fb03c36 157 * @throws SSLException
52e0732e
NR
158 * in case of I/O error (i.e., the data is not what you assumed
159 * it was)
160 */
9fb03c36
NR
161 public String encrypt64(String data, boolean zip) throws SSLException {
162 try {
163 return encrypt64(data.getBytes("UTF8"), zip);
164 } catch (UnsupportedEncodingException e) {
165 // UTF-8 is required in all confirm JVMs
166 e.printStackTrace();
167 return null;
168 }
52e0732e
NR
169 }
170
171 /**
172 * Encrypt the data, then encode it into Base64.
173 *
174 * @param data
175 * the data to encrypt
176 * @param zip
177 * TRUE to also compress the data in GZIP format; remember that
178 * compressed and not-compressed content are different; you need
179 * to know which is which when decoding
180 *
181 * @return the encrypted data, encoded in Base64
182 *
9fb03c36 183 * @throws SSLException
52e0732e
NR
184 * in case of I/O error (i.e., the data is not what you assumed
185 * it was)
186 */
9fb03c36
NR
187 public String encrypt64(byte[] data, boolean zip) throws SSLException {
188 try {
189 return StringUtils.base64(encrypt(data), zip);
190 } catch (IOException e) {
191 // not exactly true, but we consider here that this error is a crypt
192 // error, not a normal I/O error
193 throw new SSLException(e);
194 }
52e0732e
NR
195 }
196
197 /**
198 * Decode the data which is assumed to be encrypted with the same utilities.
199 *
200 * @param data
201 * the encrypted data to decode
202 *
203 * @return the original, decoded data
204 *
9fb03c36 205 * @throws SSLException
52e0732e
NR
206 * in case of I/O error
207 */
9fb03c36 208 public byte[] decrypt(byte[] data) throws SSLException {
52e0732e
NR
209 try {
210 return dcipher.doFinal(data);
211 } catch (IllegalBlockSizeException e) {
9fb03c36 212 throw new SSLException(e);
52e0732e 213 } catch (BadPaddingException e) {
9fb03c36 214 throw new SSLException(e);
52e0732e
NR
215 }
216 }
217
218 /**
219 * Decode the data which is assumed to be encrypted with the same utilities
220 * and is a Base64 encoded value.
221 *
222 * @param data
223 * the encrypted data to decode in Base64 format
224 * @param zip
225 * TRUE to also uncompress the data from a GZIP format
226 * automatically; if set to FALSE, zipped data can be returned
227 *
228 * @return the original, decoded data
229 *
9fb03c36 230 * @throws SSLException
52e0732e
NR
231 * in case of I/O error
232 */
9fb03c36
NR
233 public byte[] decrypt64(String data, boolean zip) throws SSLException {
234 try {
235 return decrypt(StringUtils.unbase64(data, zip));
236 } catch (IOException e) {
237 // not exactly true, but we consider here that this error is a crypt
238 // error, not a normal I/O error
239 throw new SSLException(e);
240 }
52e0732e
NR
241 }
242
243 /**
244 * Decode the data which is assumed to be encrypted with the same utilities
245 * and is a Base64 encoded value, then convert it into a String (this method
246 * assumes the data <b>was</b> indeed a UTF-8 encoded {@link String}).
247 *
248 * @param data
249 * the encrypted data to decode in Base64 format
250 * @param zip
251 * TRUE to also uncompress the data from a GZIP format
252 * automatically; if set to FALSE, zipped data can be returned
253 *
254 * @return the original, decoded data
255 *
9fb03c36 256 * @throws SSLException
52e0732e
NR
257 * in case of I/O error
258 */
9fb03c36
NR
259 public String decrypt64s(String data, boolean zip) throws SSLException {
260 try {
261 return new String(decrypt(StringUtils.unbase64(data, zip)), "UTF-8");
262 } catch (UnsupportedEncodingException e) {
263 // UTF-8 is required in all confirm JVMs
264 e.printStackTrace();
265 return null;
266 } catch (IOException e) {
267 // not exactly true, but we consider here that this error is a crypt
268 // error, not a normal I/O error
269 throw new SSLException(e);
270 }
52e0732e
NR
271 }
272
273 /**
274 * This is probably <b>NOT</b> secure!
275 *
276 * @param input
277 * some {@link String} input
278 *
279 * @return a 128 bits key computed from the given input
280 */
281 static private byte[] key2key(String input) {
b1ed544b 282 return StringUtils.getMd5Hash("" + input).getBytes();
52e0732e
NR
283 }
284}