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.security.SecureRandom;
31
32 import javax.crypto.Cipher;
33 import javax.crypto.SecretKey;
34 import javax.crypto.spec.GCMParameterSpec;
35 import javax.crypto.spec.SecretKeySpec;
36
37 import org.apache.fulcrum.jce.crypto.StreamUtil;
38 import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8;
39 import org.apache.fulcrum.jce.crypto.extended.CryptoStreamFactoryJ8Template;
40 import org.apache.fulcrum.jce.crypto.extended.CryptoParametersJ8.TYPES;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public final class CryptoStreamGCMImpl extends CryptoStreamFactoryJ8Template
62 {
63
64 protected static final int IV_SIZE = 12;
65
66
67
68
69
70 public CryptoStreamGCMImpl() throws GeneralSecurityException
71 {
72 this(generateSalt());
73 }
74
75
76
77
78
79
80
81
82 public CryptoStreamGCMImpl( byte[] salt)
83 {
84 setSalt(salt);
85 this.providerName = PROVIDERNAME;
86 setType(TYPES.GCM);
87 this.algorithm = CryptoParametersJ8.TYPES_IMPL.ALGORITHM_J8_GCM.getAlgorithm();
88 }
89
90
91
92
93
94
95
96
97
98 @Override
99 protected Key createKey( char[] password, byte[] salt )
100 throws GeneralSecurityException
101 {
102 SecretKey key = new SecretKeySpec(((salt == null)? this.getSalt(): salt.clone()), "AES");
103 return key;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118 @Override
119 protected byte[] createCipher(InputStream is, int mode, char[] password )
120 throws GeneralSecurityException, IOException
121 {
122 Cipher cipher;
123
124 ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
125 StreamUtil.copy(is, bos);
126 byte[] input = bos.toByteArray();
127
128 byte[] ciphertext = null;
129 byte[] salt = null;
130 byte[] iv = null;
131
132 if (mode == Cipher.DECRYPT_MODE) {
133
134 ByteBuffer byteBuffer = ByteBuffer.wrap(input);
135 salt = new byte[ SALT_SIZE ];
136 byteBuffer.get(salt);
137 iv = new byte[ IV_SIZE ];
138 byteBuffer.get(iv);
139 ciphertext = new byte[byteBuffer.remaining()];
140 byteBuffer.get(ciphertext);
141
142
143
144
145 }
146
147 Key key = this.createKey( password, salt );
148
149 if( this.getProviderName() == null )
150 {
151 cipher = Cipher.getInstance( this.getAlgorithm() );
152 }
153 else
154 {
155 cipher = Cipher.getInstance( this.getAlgorithm(), this.getProviderName() );
156 }
157
158
159 if (mode == Cipher.DECRYPT_MODE) {
160
161 GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv);
162 cipher.init( mode, key, gcmParamSpec );
163
164
165 ciphertext = cipher.doFinal(ciphertext);
166 }
167
168
169 if (mode == Cipher.ENCRYPT_MODE) {
170 iv = generateIV();
171 GCMParameterSpec gcmParamSpec = new GCMParameterSpec(128, iv);
172
173 salt = this.getSalt();
174 cipher.init( mode, key, gcmParamSpec );
175
176
177
178
179
180 byte[] result = cipher.doFinal(input);
181
182
183
184 ByteBuffer byteBuffer = ByteBuffer.allocate(salt.length + iv.length + result.length);
185 ciphertext = byteBuffer.put(salt).put(iv).put(result).array();
186
187
188
189
190
191
192 }
193 return ciphertext;
194 }
195
196
197
198
199
200
201 private byte[] generateIV( ) throws GeneralSecurityException {
202 SecureRandom random;
203 try {
204 random = SecureRandom.getInstance("SHA1PRNG");
205 byte[] iv = new byte[ IV_SIZE ];
206 random.nextBytes(iv);
207 return iv;
208 } catch (NoSuchAlgorithmException e) {
209 throw new GeneralSecurityException(e);
210 }
211 }
212
213
214
215 }