]> git.argeo.org Git - lgpl/argeo-commons.git/blob - crypto/PasswordBasedEncryption.java
Prepare next development cycle
[lgpl/argeo-commons.git] / crypto / PasswordBasedEncryption.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.util.crypto;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.security.Key;
24
25 import javax.crypto.Cipher;
26 import javax.crypto.CipherInputStream;
27 import javax.crypto.CipherOutputStream;
28 import javax.crypto.SecretKey;
29 import javax.crypto.SecretKeyFactory;
30 import javax.crypto.spec.IvParameterSpec;
31 import javax.crypto.spec.PBEKeySpec;
32 import javax.crypto.spec.SecretKeySpec;
33
34 import org.argeo.ArgeoException;
35 import org.argeo.StreamUtils;
36
37 /** Simple password based encryption / decryption */
38 public class PasswordBasedEncryption {
39 public final static Integer DEFAULT_ITERATION_COUNT = 1024;
40 public final static Integer DEFAULT_KEY_LENGTH = 256;
41 public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1";
42 public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES";
43 public final static String DEFAULT_CIPHER = "AES/CBC/PKCS5Padding";
44 public final static String DEFAULT_CHARSET = "UTF-8";
45
46 private static byte[] DEFAULT_SALT_8 = { (byte) 0xA9, (byte) 0x9B,
47 (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
48 (byte) 0x03 };
49 private static byte[] DEFAULT_IV_16 = { (byte) 0xA9, (byte) 0x9B,
50 (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
51 (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
52 (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
53
54 private final Key key;
55 private final Cipher ecipher;
56 private final Cipher dcipher;
57
58 /**
59 * This is up to the caller to clear the passed array. Neither copy of nor
60 * reference to the passed array is kept
61 */
62 public PasswordBasedEncryption(char[] password) {
63 this(password, DEFAULT_SALT_8, DEFAULT_IV_16);
64 }
65
66 /**
67 * This is up to the caller to clear the passed array. Neither copies of nor
68 * references to the passed arrays are kept
69 */
70 public PasswordBasedEncryption(char[] password, byte[] passwordSalt,
71 byte[] initializationVector) {
72 try {
73 byte[] salt = new byte[8];
74 System.arraycopy(passwordSalt, 0, salt, 0, salt.length);
75 // for (int i = 0; i < password.length && i < salt.length; i++)
76 // salt[i] = (byte) password[i];
77 byte[] iv = new byte[16];
78 System.arraycopy(initializationVector, 0, iv, 0, iv.length);
79 // for (int i = 0; i < password.length && i < iv.length; i++)
80 // iv[i] = (byte) password[i];
81
82 SecretKeyFactory keyFac = SecretKeyFactory
83 .getInstance(getSecretKeyFactoryName());
84 PBEKeySpec keySpec = new PBEKeySpec(password, salt,
85 getIterationCount(), getKeyLength());
86 String secKeyEncryption = getSecretKeyEncryption();
87 if (secKeyEncryption != null) {
88 SecretKey tmp = keyFac.generateSecret(keySpec);
89 key = new SecretKeySpec(tmp.getEncoded(),
90 getSecretKeyEncryption());
91 } else {
92 key = keyFac.generateSecret(keySpec);
93 }
94 ecipher = Cipher.getInstance(getCipherName());
95 ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
96 // AlgorithmParameters params = ecipher.getParameters();
97 // byte[] iv =
98 // params.getParameterSpec(IvParameterSpec.class).getIV();
99 dcipher = Cipher.getInstance(getCipherName());
100 dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
101 } catch (Exception e) {
102 throw new ArgeoException("Cannot get secret key", e);
103 }
104 }
105
106 public void encrypt(InputStream decryptedIn, OutputStream encryptedOut)
107 throws IOException {
108 try {
109 CipherOutputStream out = new CipherOutputStream(encryptedOut,
110 ecipher);
111 StreamUtils.copy(decryptedIn, out);
112 StreamUtils.closeQuietly(out);
113 } catch (IOException e) {
114 throw e;
115 } catch (Exception e) {
116 throw new ArgeoException("Cannot encrypt", e);
117 } finally {
118 StreamUtils.closeQuietly(decryptedIn);
119 }
120 }
121
122 public void decrypt(InputStream encryptedIn, OutputStream decryptedOut)
123 throws IOException {
124 try {
125 CipherInputStream decryptedIn = new CipherInputStream(encryptedIn,
126 dcipher);
127 StreamUtils.copy(decryptedIn, decryptedOut);
128 } catch (IOException e) {
129 throw e;
130 } catch (Exception e) {
131 throw new ArgeoException("Cannot decrypt", e);
132 } finally {
133 StreamUtils.closeQuietly(encryptedIn);
134 }
135 }
136
137 public byte[] encryptString(String str) {
138 ByteArrayOutputStream out = null;
139 ByteArrayInputStream in = null;
140 try {
141 out = new ByteArrayOutputStream();
142 in = new ByteArrayInputStream(str.getBytes(DEFAULT_CHARSET));
143 encrypt(in, out);
144 return out.toByteArray();
145 } catch (Exception e) {
146 throw new ArgeoException("Cannot encrypt", e);
147 } finally {
148 StreamUtils.closeQuietly(out);
149 }
150 }
151
152 /** Closes the input stream */
153 public String decryptAsString(InputStream in) {
154 ByteArrayOutputStream out = null;
155 try {
156 out = new ByteArrayOutputStream();
157 decrypt(in, out);
158 return new String(out.toByteArray(), DEFAULT_CHARSET);
159 } catch (Exception e) {
160 throw new ArgeoException("Cannot decrypt", e);
161 } finally {
162 StreamUtils.closeQuietly(out);
163 }
164 }
165
166 protected Key getKey() {
167 return key;
168 }
169
170 protected Cipher getEcipher() {
171 return ecipher;
172 }
173
174 protected Cipher getDcipher() {
175 return dcipher;
176 }
177
178 protected Integer getIterationCount() {
179 return DEFAULT_ITERATION_COUNT;
180 }
181
182 protected Integer getKeyLength() {
183 return DEFAULT_KEY_LENGTH;
184 }
185
186 protected String getSecretKeyFactoryName() {
187 return DEFAULT_SECRETE_KEY_FACTORY;
188 }
189
190 protected String getSecretKeyEncryption() {
191 return DEFAULT_SECRETE_KEY_ENCRYPTION;
192 }
193
194 protected String getCipherName() {
195 return DEFAULT_CIPHER;
196 }
197 }