1 package org.apache.fulcrum.jce.crypto.algo;
2
3 import java.io.ByteArrayOutputStream;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.nio.ByteBuffer;
27 import java.security.GeneralSecurityException;
28 import java.security.Key;
29 import java.security.NoSuchAlgorithmException;
30 import java.util.Arrays;
31
32 import javax.crypto.Cipher;
33 import javax.crypto.SecretKeyFactory;
34 import javax.crypto.spec.IvParameterSpec;
35 import javax.crypto.spec.PBEKeySpec;
36 import javax.crypto.spec.PBEParameterSpec;
37
38 import org.apache.fulcrum.jce.crypto.StreamUtil;
39 import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
40 import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
41 import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public final class CryptoStreamPBEImpl extends CryptoStreamFactoryJ8Template
67 {
68
69 protected static final int IV_SIZE = 16;
70
71 protected static final int KEY_SIZE = 256;
72
73
74
75
76 protected static final int COUNT_J8 = 10_000;
77
78
79
80
81
82
83
84 public CryptoStreamPBEImpl() throws GeneralSecurityException
85 {
86 this(generateSalt(), COUNT_J8);
87 }
88
89
90
91
92
93
94 public CryptoStreamPBEImpl( byte[] salt)
95 {
96 this(salt, COUNT_J8);
97
98 }
99
100
101
102
103
104
105
106
107 public CryptoStreamPBEImpl( byte[] salt, int count)
108 {
109 setSalt(salt);
110 this.count = count;
111 this.providerName = PROVIDERNAME;
112 setType(TYPES.PBE);
113 this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_PBE.getAlgorithm();
114 }
115
116
117
118
119
120
121
122
123
124 @Override
125 protected Key createKey( char[] password, byte[] salt )
126 throws GeneralSecurityException
127 {
128 SecretKeyFactory keyFactory;
129 String algorithm = this.getAlgorithm();
130
131 PBEKeySpec keySpec = new PBEKeySpec(password, (salt == null)? this.getSalt(): salt.clone(), this.getCount(), KEY_SIZE );
132
133 byte[] encodedTmp = null;
134 try {
135 if( this.getProviderName() == null )
136 {
137 keyFactory = SecretKeyFactory.getInstance( algorithm );
138 }
139 else
140 {
141 keyFactory = SecretKeyFactory.getInstance( algorithm, this.getProviderName() );
142 }
143 return keyFactory.generateSecret(keySpec);
144
145 } catch (NoSuchAlgorithmException e) {
146 throw new GeneralSecurityException(e);
147 } finally {
148 if (encodedTmp != null) {
149 Arrays.fill(encodedTmp, (byte)0);
150 }
151 if (keySpec != null) {
152 keySpec.clearPassword();
153 }
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169 @Override
170 protected byte[] createCipher(InputStream is, int mode, char[] password )
171 throws GeneralSecurityException, IOException
172 {
173 Cipher cipher;
174 PBEParameterSpec paramSpec = null;
175
176 ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
177 StreamUtil.copy(is, bos);
178 byte[] input = bos.toByteArray();
179
180 byte[] ciphertext = null;
181
182 byte[] salt = null;
183 byte[] iv = null;
184 if (mode == Cipher.DECRYPT_MODE) {
185
186 ByteBuffer byteBuffer = ByteBuffer.wrap(input);
187 salt = new byte[SALT_SIZE ];
188 byteBuffer.get(salt);
189 iv = new byte[ IV_SIZE ];
190 byteBuffer.get(iv);
191 ciphertext = new byte[byteBuffer.remaining()];
192 byteBuffer.get(ciphertext);
193
194
195
196
197 }
198
199 Key key = this.createKey( password, salt );
200
201 if( this.getProviderName() == null )
202 {
203 cipher = Cipher.getInstance( this.getAlgorithm() );
204 }
205 else
206 {
207 cipher = Cipher.getInstance( this.getAlgorithm(), this.getProviderName() );
208 }
209
210
211 if (mode == Cipher.DECRYPT_MODE) {
212
213 paramSpec = new PBEParameterSpec( salt, this.getCount(), new IvParameterSpec(iv) );
214
215 cipher.init( mode, key, paramSpec );
216
217 ciphertext = cipher.doFinal(ciphertext);
218 }
219
220
221 if (mode == Cipher.ENCRYPT_MODE) {
222 paramSpec = new PBEParameterSpec( this.getSalt(), this.getCount() );
223 salt = paramSpec.getSalt();
224 cipher.init( mode, key, paramSpec );
225
226
227 byte[] result = cipher.doFinal(input);
228 iv = cipher.getIV();
229
230
231 ByteBuffer byteBuffer = ByteBuffer.allocate(salt.length + iv.length + result.length);
232 ciphertext = byteBuffer.put(salt).put(iv).put(result).array();
233
234
235
236
237
238 }
239 return ciphertext;
240 }
241
242 }