1 package org
.argeo
.util
.crypto
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.ByteArrayOutputStream
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.io
.OutputStream
;
8 import java
.security
.Key
;
10 import javax
.crypto
.Cipher
;
11 import javax
.crypto
.CipherInputStream
;
12 import javax
.crypto
.CipherOutputStream
;
13 import javax
.crypto
.SecretKey
;
14 import javax
.crypto
.SecretKeyFactory
;
15 import javax
.crypto
.spec
.IvParameterSpec
;
16 import javax
.crypto
.spec
.PBEKeySpec
;
17 import javax
.crypto
.spec
.SecretKeySpec
;
19 import org
.argeo
.ArgeoException
;
20 import org
.argeo
.StreamUtils
;
22 /** Simple password based encryption / decryption */
23 public class PasswordBasedEncryption
{
24 public final static Integer DEFAULT_ITERATION_COUNT
= 1024;
25 public final static Integer DEFAULT_KEY_LENGTH
= 256;
26 public final static String DEFAULT_SECRETE_KEY_FACTORY
= "PBKDF2WithHmacSHA1";
27 public final static String DEFAULT_SECRETE_KEY_ENCRYPTION
= "AES";
28 public final static String DEFAULT_CIPHER
= "AES/CBC/PKCS5Padding";
29 public final static String DEFAULT_CHARSET
= "UTF-8";
31 private static byte[] DEFAULT_SALT_8
= { (byte) 0xA9, (byte) 0x9B,
32 (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
34 private static byte[] DEFAULT_IV_16
= { (byte) 0xA9, (byte) 0x9B,
35 (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
36 (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
37 (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
39 private final Key key
;
40 private final Cipher ecipher
;
41 private final Cipher dcipher
;
44 * This is up to the caller to clear the passed array. Neither copy of nor
45 * reference to the passed array is kept
47 public PasswordBasedEncryption(char[] password
) {
48 this(password
, DEFAULT_SALT_8
, DEFAULT_IV_16
);
52 * This is up to the caller to clear the passed array. Neither copies of nor
53 * references to the passed arrays are kept
55 public PasswordBasedEncryption(char[] password
, byte[] passwordSalt
,
56 byte[] initializationVector
) {
58 byte[] salt
= new byte[8];
59 System
.arraycopy(passwordSalt
, 0, salt
, 0, salt
.length
);
60 // for (int i = 0; i < password.length && i < salt.length; i++)
61 // salt[i] = (byte) password[i];
62 byte[] iv
= new byte[16];
63 System
.arraycopy(initializationVector
, 0, iv
, 0, iv
.length
);
64 // for (int i = 0; i < password.length && i < iv.length; i++)
65 // iv[i] = (byte) password[i];
67 SecretKeyFactory keyFac
= SecretKeyFactory
68 .getInstance(getSecretKeyFactoryName());
69 PBEKeySpec keySpec
= new PBEKeySpec(password
, salt
,
70 getIterationCount(), getKeyLength());
71 String secKeyEncryption
= getSecretKeyEncryption();
72 if (secKeyEncryption
!= null) {
73 SecretKey tmp
= keyFac
.generateSecret(keySpec
);
74 key
= new SecretKeySpec(tmp
.getEncoded(),
75 getSecretKeyEncryption());
77 key
= keyFac
.generateSecret(keySpec
);
79 ecipher
= Cipher
.getInstance(getCipherName());
80 ecipher
.init(Cipher
.ENCRYPT_MODE
, key
, new IvParameterSpec(iv
));
81 // AlgorithmParameters params = ecipher.getParameters();
83 // params.getParameterSpec(IvParameterSpec.class).getIV();
84 dcipher
= Cipher
.getInstance(getCipherName());
85 dcipher
.init(Cipher
.DECRYPT_MODE
, key
, new IvParameterSpec(iv
));
86 } catch (Exception e
) {
87 throw new ArgeoException("Cannot get secret key", e
);
91 public void encrypt(InputStream decryptedIn
, OutputStream encryptedOut
)
94 CipherOutputStream out
= new CipherOutputStream(encryptedOut
,
96 StreamUtils
.copy(decryptedIn
, out
);
97 StreamUtils
.closeQuietly(out
);
98 } catch (IOException e
) {
100 } catch (Exception e
) {
101 throw new ArgeoException("Cannot encrypt", e
);
103 StreamUtils
.closeQuietly(decryptedIn
);
107 public void decrypt(InputStream encryptedIn
, OutputStream decryptedOut
)
110 CipherInputStream decryptedIn
= new CipherInputStream(encryptedIn
,
112 StreamUtils
.copy(decryptedIn
, decryptedOut
);
113 } catch (IOException e
) {
115 } catch (Exception e
) {
116 throw new ArgeoException("Cannot decrypt", e
);
118 StreamUtils
.closeQuietly(encryptedIn
);
122 public byte[] encryptString(String str
) {
123 ByteArrayOutputStream out
= null;
124 ByteArrayInputStream in
= null;
126 out
= new ByteArrayOutputStream();
127 in
= new ByteArrayInputStream(str
.getBytes(DEFAULT_CHARSET
));
129 return out
.toByteArray();
130 } catch (Exception e
) {
131 throw new ArgeoException("Cannot encrypt", e
);
133 StreamUtils
.closeQuietly(out
);
137 /** Closes the input stream */
138 public String
decryptAsString(InputStream in
) {
139 ByteArrayOutputStream out
= null;
141 out
= new ByteArrayOutputStream();
143 return new String(out
.toByteArray(), DEFAULT_CHARSET
);
144 } catch (Exception e
) {
145 throw new ArgeoException("Cannot decrypt", e
);
147 StreamUtils
.closeQuietly(out
);
151 protected Key
getKey() {
155 protected Cipher
getEcipher() {
159 protected Cipher
getDcipher() {
163 protected Integer
getIterationCount() {
164 return DEFAULT_ITERATION_COUNT
;
167 protected Integer
getKeyLength() {
168 return DEFAULT_KEY_LENGTH
;
171 protected String
getSecretKeyFactoryName() {
172 return DEFAULT_SECRETE_KEY_FACTORY
;
175 protected String
getSecretKeyEncryption() {
176 return DEFAULT_SECRETE_KEY_ENCRYPTION
;
179 protected String
getCipherName() {
180 return DEFAULT_CIPHER
;