1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.mailet.crypto;
23
24 import java.io.BufferedInputStream;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.security.InvalidAlgorithmParameterException;
29 import java.security.KeyStore;
30 import java.security.KeyStoreException;
31 import java.security.NoSuchAlgorithmException;
32 import java.security.NoSuchProviderException;
33 import java.security.PrivateKey;
34 import java.security.UnrecoverableKeyException;
35 import java.security.cert.CertStore;
36 import java.security.cert.CertStoreException;
37 import java.security.cert.CertificateException;
38 import java.security.cert.CollectionCertStoreParameters;
39 import java.security.cert.X509Certificate;
40 import java.util.ArrayList;
41 import java.util.Enumeration;
42
43 import javax.mail.internet.MimeBodyPart;
44 import javax.mail.internet.MimeMessage;
45 import javax.mail.internet.MimeMultipart;
46
47 import org.bouncycastle.mail.smime.SMIMEException;
48 import org.bouncycastle.mail.smime.SMIMESignedGenerator;
49
50
51
52
53
54
55
56
57
58
59 public class SMIMEKeyHolder implements KeyHolder{
60
61
62
63
64
65
66 public static String getDefaultType() {
67 return KeyStore.getDefaultType();
68 }
69
70
71
72
73 private PrivateKey privateKey;
74
75
76
77
78 private X509Certificate certificate;
79
80
81
82
83 private CertStore certStore;
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public SMIMEKeyHolder(String keyStoreFileName, String keyStorePassword, String keyAlias, String keyAliasPassword, String keyStoreType)
107 throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
108 CertificateException, UnrecoverableKeyException, NoSuchProviderException {
109
110 try {
111 InitJCE.init();
112 } catch (InstantiationException e) {
113 NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
114 ex.initCause(e);
115 throw ex;
116 } catch (IllegalAccessException e) {
117 NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
118 ex.initCause(e);
119 throw ex;
120 } catch (ClassNotFoundException e) {
121 NoSuchProviderException ex = new NoSuchProviderException("Error during cryptography provider initialization. Has bcprov-jdkxx-yyy.jar been copied in the lib directory or installed in the system?");
122 ex.initCause(e);
123 throw ex;
124 }
125
126 if (keyStoreType == null) {
127 keyStoreType = KeyStore.getDefaultType();
128 }
129
130 KeyStore keyStore = KeyStore.getInstance(keyStoreType);
131 keyStore.load(new BufferedInputStream(new FileInputStream(keyStoreFileName)), keyStorePassword.toCharArray());
132
133 Enumeration aliases = keyStore.aliases();
134 if (keyAlias == null) {
135 if(aliases.hasMoreElements()) {
136 keyAlias = (String) aliases.nextElement();
137 } else {
138 throw new KeyStoreException("No alias was found in keystore.");
139 }
140 if (aliases.hasMoreElements()) {
141 throw new KeyStoreException("No <keyAlias> was given and more than one alias was found in keystore.");
142
143 }
144 }
145
146 if (keyAliasPassword == null) {
147 keyAliasPassword = keyStorePassword;
148 }
149
150 this.privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyAliasPassword.toCharArray());
151 if (this.privateKey == null) {
152 throw new KeyStoreException("The \"" + keyAlias + "\" PrivateKey alias was not found in keystore.");
153 }
154
155 this.certificate = (X509Certificate) keyStore.getCertificate(keyAlias);
156 if (this.certificate == null) {
157 throw new KeyStoreException("The \"" + keyAlias + "\" X509Certificate alias was not found in keystore.");
158 }
159 java.security.cert.Certificate[] certificateChain = keyStore.getCertificateChain(keyAlias);
160 ArrayList certList = new ArrayList();
161 if (certificateChain == null) {
162 certList.add(this.certificate);
163 } else {
164 for (int i = 0; i < certificateChain.length; i++) {
165 certList.add(certificateChain[i]);
166 }
167 }
168
169
170
171 this.certStore = CertStore.getInstance("Collection",
172 new CollectionCertStoreParameters(certList), "BC");
173
174 }
175
176
177
178
179
180 public PrivateKey getPrivateKey() {
181 return this.privateKey;
182 }
183
184
185
186
187
188 public X509Certificate getCertificate() {
189 return this.certificate;
190 }
191
192
193
194
195
196 public CertStore getCertStore() {
197 return this.certStore;
198 }
199
200
201
202
203
204
205 public SMIMESignedGenerator createGenerator() throws CertStoreException, SMIMEException {
206
207
208 SMIMESignedGenerator generator = new SMIMESignedGenerator();
209
210
211
212 generator.addSigner(this.privateKey, this.certificate, SMIMESignedGenerator.DIGEST_SHA1);
213
214
215 generator.addCertificatesAndCRLs(this.certStore);
216
217 return generator;
218
219 }
220
221
222
223
224
225
226 public MimeMultipart generate(MimeMessage message) throws CertStoreException,
227 NoSuchAlgorithmException, NoSuchProviderException, SMIMEException {
228
229
230 SMIMESignedGenerator generator = createGenerator();
231
232
233 return generator.generate(message, "BC");
234
235 }
236
237
238
239
240
241
242 public MimeMultipart generate(MimeBodyPart content) throws CertStoreException,
243 NoSuchAlgorithmException, NoSuchProviderException, SMIMEException {
244
245
246 SMIMESignedGenerator generator = createGenerator();
247
248
249 return generator.generate(content, "BC");
250
251 }
252
253
254
255
256
257
258 public static String getSignerDistinguishedName(X509Certificate certificate) {
259
260 return certificate.getSubjectDN().toString();
261
262 }
263
264
265
266
267
268
269
270 public static String getSignerCN(X509Certificate certificate) {
271
272 return extractAttribute(certificate.getSubjectDN().toString(), "CN=");
273
274 }
275
276
277
278
279
280
281
282 public static String getSignerAddress(X509Certificate certificate) {
283
284 return extractAttribute(certificate.getSubjectDN().toString(), "EMAILADDRESS=");
285
286 }
287
288
289
290
291
292
293 public String getSignerDistinguishedName() {
294 return getSignerDistinguishedName(getCertificate());
295 }
296
297
298
299
300
301
302 public String getSignerCN() {
303 return getSignerCN(getCertificate());
304 }
305
306
307
308
309
310
311 public String getSignerAddress() {
312 return getSignerAddress(getCertificate());
313 }
314
315 private static String extractAttribute(String DistinguishedName, String attributeName) {
316
317 int i = DistinguishedName.indexOf(attributeName);
318
319 if (i < 0) {
320 return null;
321 }
322
323 i += attributeName.length();
324 int j = DistinguishedName.indexOf(",", i);
325
326 if (j - 1 <= 0) {
327 return null;
328 }
329
330 return DistinguishedName.substring(i, j).trim();
331
332 }
333
334 }