KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > oyster > smime > BaseSignedSMIMEObject


1 /*
2 * Title: Oyster Project
3 * Description: S/MIME email sending capabilities
4 * @Author Vladimir Radisic
5 * @Version 2.1.5
6  */

7 package org.enhydra.oyster.smime;
8
9 import org.enhydra.oyster.exception.SMIMEException;
10 import org.enhydra.oyster.util.PFXUtils;
11 import org.enhydra.oyster.crypto.consts.SignedConstants;
12 import java.util.Vector JavaDoc;
13 import java.io.FileInputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.security.PrivateKey JavaDoc;
16 import java.security.KeyStore JavaDoc;
17 import java.security.cert.X509Certificate JavaDoc;
18 import java.security.cert.Certificate JavaDoc;
19 import javax.mail.internet.MimeMessage JavaDoc;
20
21 /**
22  * This class is used as super class for SignedSMIME and SignedAndEnvelopedSMIME
23  * classes. It contains the common methods for this two classes.
24  */

25 public class BaseSignedSMIMEObject extends BaseSMIMEObject implements SignedConstants
26 {
27
28   /**
29    * Simple constructor. Dynamically loads the BC and SUN provider necessary for
30    * cryptography processing. This constructor does not create MIME message
31    * object, so it is obligatory to invoke initMimeMessage() method after this
32    * constructor.
33    */

34   protected BaseSignedSMIMEObject ()
35   {
36     super();
37   }
38
39
40   /**
41    * Initializes the JavaMail session for SMTP and the MimeMessage object for message
42    * which will be sent. Dynamically loads the BC and SUN provider necessary for
43    * cryptography processing. This constructor is used for creating message with
44    * text/plain content. For creating html formated content (text/html), other
45    * constructor should be used in combination with one of setContent methods.
46    * Note that after using this constructor setContent method can be used only
47    * if "content" argument of constructor was given as null, otherwise setContent
48    * method can't be used because content is already set as text/plain.
49    * @param smtpHost name of SMTP host used for sending email
50    * @param fromAddress email address of sender (FROM field in email header)
51    * @param subject subject of email (SUBJECT field in email header). This
52    * argument can be null, but email message will be sent withouth SUBJECT.
53    * @param content text/plain content of email message. This argument can be
54    * null, but later one of setContent() methods or one of addAttachment()
55    * methods should be called
56    * @param charset character set for passed subject and content. The given
57    * Unicode string will be charset-encoded using the specified charset. The
58    * charset is also used to set the "charset" parameter. For example German
59    * letters should be encoded by usage of 'ISO-8859-1' charset. If charset
60    * parameter is null and subject or content contains non US-ASCII characters,
61    * it will be encoded using the platform's default charset.
62    * @exception SMIMEException if smtpHost or fromAddress parameters are null.
63    * Also, it can be caused by non SMIMEException which is MessagingException.
64    */

65   protected BaseSignedSMIMEObject (String JavaDoc smtpHost, String JavaDoc fromAddress, String JavaDoc subject,
66                           String JavaDoc content, String JavaDoc charset) throws SMIMEException
67   {
68     super(smtpHost, fromAddress, subject, content, charset);
69   }
70
71
72   /**
73    * Initializes the JavaMail session for SMTP and the MimeMessage object for message
74    * which will be sent. Dynamically loads the BC and SUN provider necessary for
75    * cryptography processing. This constructor does not create content of message
76    * and it can be set later with one of setContent methods. Also, message can be
77    * left withouth content, but then at least one attachement must be added.
78    * @param smtpHost name of SMTP host used for sending email
79    * @param fromAddress email address of sender (FROM field in email header)
80    * @param subject subject of email (SUBJECT field in email header). This
81    * argument can be null, but email message will be sent withouth SUBJECT.
82    * @param charset character set for passed subject and content. The given
83    * Unicode string will be charset-encoded using the specified charset. The
84    * charset is also used to set the "charset" parameter. For example German
85    * letters should be encoded by usage of 'ISO-8859-1' charset. If charset
86    * parameter is null and subject or content contains non US-ASCII characters,
87    * it will be encoded using the platform's default charset.
88    * @exception SMIMEException if smtpHost or fromAddress parameters are null.
89    * Also, it can be caused by non SMIMEException which is MessagingException.
90    */

91   protected BaseSignedSMIMEObject (String JavaDoc smtpHost, String JavaDoc fromAddress, String JavaDoc subject,
92                           String JavaDoc charset) throws SMIMEException
93   {
94     super(smtpHost, fromAddress, subject, null, charset);
95   }
96
97
98   /**
99    * Construction of message with external prepared MimeMessage object. Usage of
100    * this constructor disables usage of setContent() and addAttachment() methods.
101    * Also, all recipients (TO, CC or BCC type) must be declared again via
102    * setRecipient() method, even if they were previously set. Be very carefull
103    * with usage of this constructor because all MimeBodyPart objects and
104    * MimeMultipart objects used in construction of given MimeMessage object,
105    * must have correct defined Content header arguments, and contents. Contents
106    * must be formed in format which can be recognised and appropriate interpreted
107    * in the process of sending mail. If there is any special content object
108    * added to MimeBodyPart object or MimeMultipart object, the appropriate
109    * DataContent handler must be created for that object and set to corresponding
110    * BodyPart.
111    * @param mimeMessage external created MimeMessage object
112    * @exception SMIMEException if smtpHost or fromAddress parameter is null.
113    * Also, it can be caused by non SMIMEException which is MessagingException.
114    */

115   protected BaseSignedSMIMEObject (MimeMessage JavaDoc mimeMessage) throws SMIMEException
116   {
117     super(mimeMessage);
118   }
119
120
121
122   /**
123    * Storage for .pfx files corresponding to appropriate signing session (used
124    * for first type of addSigner function).
125    */

126   protected Vector JavaDoc ksArray = new Vector JavaDoc(0, 1);
127
128   /**
129    * Storage for digest algorithm corresponding to appropriate signing session
130    * (used for first type of addSigner function).
131    */

132   protected Vector JavaDoc digestArray = new Vector JavaDoc(0, 1);
133
134   /**
135    * Storage for byte[2] grouped indicators (used for first type of addSigner
136    * function).
137    */

138   protected Vector JavaDoc including = new Vector JavaDoc(0, 1);
139
140   /**
141    * Storage for certificate chain corresponding to appropriate signing session
142    * (used for second type of addSigner function)
143    */

144   protected Vector JavaDoc certChainArray = new Vector JavaDoc(0, 1);
145
146   /**
147    * Storage for private key corresponding to appropriate signing session (used
148    * for second type of addSigner function)
149    */

150   protected Vector JavaDoc privKeyArray = new Vector JavaDoc(0, 1);
151
152   /**
153    * Storage for digest algorithm corresponding to appropriate signing session
154    * (used for second type of addSigner function)
155    */

156   protected Vector JavaDoc digestArray2 = new Vector JavaDoc(0, 1);
157
158   /**
159    * Storage for byte[2] grouped indicators (used for second type of addSigner
160    * function)
161    */

162   protected Vector JavaDoc including2 = new Vector JavaDoc(0, 1);
163
164   /**
165    * Storage for additional certificates
166    */

167   protected Vector JavaDoc aditionalCerts = new Vector JavaDoc(0, 1);
168
169   /**
170    * Temporary storage for capabilities (after method addSigner, this object is
171    * copied to capabilities or capabilities2).
172    */

173   protected Vector JavaDoc capabilitiesTemp = new Vector JavaDoc(0, 1);
174
175   /**
176    * Storage for capabilities (used for first type of addSigner function)
177    */

178   protected Vector JavaDoc capabilities = new Vector JavaDoc(0, 1);
179
180   /**
181    * Storage for capabilities (used for second type of addSigner function)
182    */

183   protected Vector JavaDoc capabilities2 = new Vector JavaDoc(0, 1);
184
185
186   /**
187    * Sets Capabilities Attributes (method is optional, but if exists, must be
188    * performed before addSigner method). Depending on parameter type0, other five
189    * parameters make order in specific group of algorithms. Groups of algorithms
190    * with positions of specific algorithms are:<BR>
191    * (SIGNATURE, MD2 with RSA, MD5 with RSA, SHA1 with RSA, SHA1 with DSA, Unused field)<BR>
192    * (SYMMETRIC, RC2 40 bits, RC2 64 bits, RC2 128 bits, DES, DES_EDE3)<BR>
193    * (ENCIPHER, RSA, Unused field, Unused field, Unused field, Unused field)<BR>
194    * <BR>
195    * For example, if we wish to set Capabilities Attributes for symmetric algorithms
196    * in order: RC2 64 bits, RC2 40 bits and DES, encipher algorithm RSA (only possible
197    * in this version), and signature algorithms in order: SHA1 with RSA, MD5 with RSA
198    * and MD2 with RSA, we should make following lines of code<BR>
199    * <BR>
200    * setCapabilities ("SYMMETRIC", 2, 1, 0, 3, 0)<BR>
201    * setCapabilities ("ENCIPHER", 1, 0, 0, 0, 0)<BR>
202    * setCapabilities ("SIGNATURE", 3, 2, 1, 0, 0)<BR>
203    * <BR>
204    * 0 means exclusion of algorithm from the specified position in the method. It is
205    * free to decide which algorithm will be included, or which group of algorithm
206    * will be included in Capabilities Attributes. If no groups are added, capabilities
207    * attributes won't be added to Signed Attributes. If two or more signers will
208    * sign the message, and their capabilities are different, this method should
209    * be performed before every signing if we wish to specify Capabilities
210    * Attributes for all particular signers. If type0 parameter is set as:<BR>
211    * setCapabilities ("DEFAULT", 0, 0, 0, 0, 0)<BR>
212    * it is equivalent to:<BR>
213    * setCapabilities ("SYMMETRIC", 1, 0, 0, 0, 0)<BR>
214    * setCapabilities ("ENCIPHER", 0, 0, 1, 0, 0)<BR>
215    * setCapabilities ("SIGNATURE", 1, 0, 0, 0, 0)<BR>
216    * @param type0 sets group of algorithms for capabilities attributes. It can be set
217    * with values: SIGNATURE, SYMMETRIC, ENCIPHER or DEFAULT.
218    * @param par10 sets order in group of parameters, or excludes some algorithms
219    * from capabilities atributes. Can take values 1, 2, 3, 4 or 5 and 0 for
220    * exclusion of the particular algorithm.
221    * @param par20 same as for par10
222    * @param par30 same as for par10
223    * @param par40 same as for par10
224    * @param par50 same as for par10
225    * @exception SMIMEException if method is performed more than three times for one signer,
226    * or in case of wrong values of parameters.
227    */

228   public void setCapabilities (String JavaDoc type0, int par10, int par20, int par30,
229                                int par40, int par50) throws SMIMEException
230   {
231     int[] tempType = { par10, par20, par30, par40, par50 };
232     capabilitiesTemp.addElement(type0);
233     capabilitiesTemp.addElement(tempType);
234     if (capabilitiesTemp.size() > 6)
235       throw new SMIMEException(this, 1045);
236   }
237
238   /**
239    * Adds signer to signed and enveloped S/MIME message.
240    * @param pfxfileName path and file name with certificate and private key
241    * corresponding to the sender of the message (file with .p12 or .pfx extension)
242    * @param password used to access to .pfx or .p12 file
243    * @param signingAlg algorithm used for signing (can be SHA1_WITH_RSA,
244    * MD2_WITH_RSA, MD5_WITH_RSA or SHA1_WITH_DSA).
245    * @param includingCert including/not including certificates to signed
246    * message
247    * @param includingSignAttrib including/not including signed attributes
248    * to signed message. Must be set to true in case of implicit signing
249    * @exception SMIMEException caused by non SMIMEException which can be one of the
250    * following: FileNotFoundException, NoSuchProviderException, KeyStoreException
251    * CertificateException, NoSuchAlgorithmException or IOException.
252    */

253   public void addSigner (String JavaDoc pfxfileName, String JavaDoc password, String JavaDoc signingAlg,
254                          boolean includingCert, boolean includingSignAttrib) throws SMIMEException
255   {
256     try {
257       char[] paswCh = password.toCharArray();
258       FileInputStream JavaDoc inPFX = new FileInputStream JavaDoc(pfxfileName);
259       KeyStore JavaDoc ks = KeyStore.getInstance("PKCS12", "BC");
260       ks.load(inPFX, paswCh);
261       inPFX.close();
262       boolean[] incl = { includingCert, includingSignAttrib };
263       ksArray.addElement(ks);
264       digestArray.addElement(signingAlg);
265       including.addElement(incl);
266       if (capabilitiesTemp.size() != 0) {
267         for (int i = 0; i != capabilitiesTemp.size(); i++)
268           capabilities.addElement(capabilitiesTemp.elementAt(i));
269       }
270       for (int i = 0; i != (6 - capabilitiesTemp.size()); i++)
271         capabilities.addElement(null);
272       capabilitiesTemp = new Vector JavaDoc(0, 1);
273     }
274     catch(Exception JavaDoc e) {
275       throw SMIMEException.getInstance(this, e, "addSigner");
276     }
277   }
278
279   /**
280    * Adds signer to signed and enveloped S/MIME message.
281    * @param chain certificate chain. First certificate in array must be
282    * owner's certificate, and last certificate has to be root certificate
283    * @param privKey private key corresponding to owner's certificate (DSA
284    * or RSA depend on type of signing)
285    * @param signingAlg algorithm used for signing (can be SHA1_WITH_RSA,
286    * MD2_WITH_RSA, MD5_WITH_RSA or SHA1_WITH_DSA).
287    * @param includingCert including/not including certificates to signed
288    * message
289    * @param includingSignAttrib including/not including signed attributes
290    * to signed message. Must be set to true in case of implicit signing.
291    */

292   public void addSigner (X509Certificate JavaDoc[] chain, PrivateKey JavaDoc privKey, String JavaDoc signingAlg,
293                          boolean includingCert, boolean includingSignAttrib)
294   {
295     boolean[] incl = { includingCert, includingSignAttrib };
296     certChainArray.addElement(chain);
297     privKeyArray.addElement(privKey);
298     digestArray2.addElement(signingAlg);
299     including2.addElement(incl);
300     if (capabilitiesTemp.size() != 0) {
301       for (int i = 0; i != capabilitiesTemp.size(); i++)
302         capabilities2.addElement(capabilitiesTemp.elementAt(i));
303     }
304     for (int i = 0; i != (6 - capabilitiesTemp.size()); i++)
305       capabilities2.addElement(null);
306     capabilitiesTemp = new Vector JavaDoc(0, 1);
307   }
308
309   /**
310    * Adds signer to signed and enveloped S/MIME message.
311    * @param kStore instance of KeyStore class which represents an in-memory
312    * collection of keys and certificates.
313    * @param password password used to access the corresponding private key,
314    * stored in given KeyStore object.
315    * @param alias alias name which corresponds to desired private key. If alias
316    * is given as null, then reading results are unpredictable.
317    * @param signingAlg algorithm used for signing (can be SHA1_WITH_RSA,
318    * MD2_WITH_RSA, MD5_WITH_RSA or SHA1_WITH_DSA).
319    * @param includingCert including/not including certificates to signed
320    * message
321    * @param includingSignAttrib including/not including signed attributes
322    * to signed message. Must be set to true in case of implicit signing.
323    * @exception SMIMEException caused by non SMIMEException which can be one
324    * of the following: KeyStoreException, UnrecoverableKeyException or
325    * NoSuchAlgorithmException.
326    */

327   public void addSigner (KeyStore JavaDoc kStore, String JavaDoc password, String JavaDoc alias, String JavaDoc signingAlg,
328                          boolean includingCert, boolean includingSignAttrib) throws SMIMEException
329   {
330     try {
331       char[] paswCh = password.toCharArray();
332       X509Certificate JavaDoc[] chain = null;
333       PrivateKey JavaDoc privKey = null;
334
335       if (alias != null) {
336         Certificate JavaDoc[] certs = kStore.getCertificateChain(alias);
337         if (certs != null && certs.length > 0) {
338           chain = new X509Certificate JavaDoc[certs.length];
339           for (int i = 0; i != certs.length; i++)
340             chain[i] = (X509Certificate JavaDoc) certs[i];
341         }
342         privKey = (PrivateKey JavaDoc) kStore.getKey(alias, paswCh);
343       }
344       else {
345           chain = PFXUtils.getCertificateChain(kStore);
346           if (chain == null)
347             chain = PFXUtils.getAllX509Certificate(kStore);
348
349           privKey = PFXUtils.getPrivateKey(kStore);
350       }
351
352       this.addSigner(chain, privKey, signingAlg, includingCert, includingSignAttrib);
353     }
354     catch (Exception JavaDoc e) {
355       throw SMIMEException.getInstance(this, e, "addSigner");
356     }
357   }
358
359   /**
360    * Adds signer to signed and enveloped S/MIME message.
361    * @param ksPath is path to the file representation of KeyStore which holds
362    * collection of keys and certificates. This file can be PKCS12 type (file
363    * with .p12 or .pfx extension) or can be key store of other types readable
364    * by 'BouncyCastle' or 'Sun' KeyStore implementation.
365    * @param ksType is type of KeyStore. It can be one of the following types:
366    * JKS for 'Sun' KeyStore, 'BKS', 'PKCS12' or 'UBER') for 'BouncyCastle'
367    * KeyStore. If ksType is given as null it will be assumed that PKCS12 type is
368    * in use, and alias parameter will be ignored, so this method becomes
369    * equivalent to addSigner() method which deal only with .pfx or .p12 files.
370    * @param password password used to access the corresponding private key,
371    * stored in given KeyStore file.
372    * @param alias alias name which corresponds to desired private key. If alias
373    * is given as null, then reading results are unpredictable.
374    * @param signingAlg algorithm used for signing (can be SHA1_WITH_RSA,
375    * MD2_WITH_RSA, MD5_WITH_RSA or SHA1_WITH_DSA).
376    * @param includingCert including/not including certificates to signed
377    * message
378    * @param includingSignAttrib including/not including signed attributes
379    * to signed message. Must be set to true in case of implicit signing.
380    * @exception SMIMEException if wrong path to KeyStore file ia given. Also,
381    * it can be caused by non SMIMEException which can be one of the following:
382    * FileNotFoundException, KeyStoreException, IOException, CertificateException
383    * or NoSuchAlgorithmException.
384    */

385   public void addSigner (String JavaDoc ksPath, String JavaDoc ksType, String JavaDoc password, String JavaDoc alias, String JavaDoc signingAlg,
386                          boolean includingCert, boolean includingSignAttrib) throws SMIMEException
387   {
388     char[] paswCh = password.toCharArray();
389     File JavaDoc fks = new File JavaDoc(ksPath);
390     if (! (fks.exists() && fks.isFile()))
391       throw new SMIMEException(this, 1034);
392
393     try {
394       if (ksType == null) // assumed PKCS12
395
this.addSigner(ksPath, password, signingAlg, includingCert, includingSignAttrib);
396       else {
397         FileInputStream JavaDoc fis = new FileInputStream JavaDoc(fks);
398         KeyStore JavaDoc kStore = KeyStore.getInstance(ksType);
399         kStore.load(fis, paswCh);
400         fis.close();
401
402         this.addSigner (kStore, password, alias, signingAlg, includingCert, includingSignAttrib);
403       }
404     }
405     catch (Exception JavaDoc e) {
406       throw SMIMEException.getInstance(this, e, "addSigner");
407     }
408   }
409
410   /**
411    * Adds additional certificate to signed message.
412    * @param cert X509 certificate
413    */

414   public void addCertificate (X509Certificate JavaDoc cert) {
415     aditionalCerts.addElement(cert);
416   }
417
418   /**
419    * Resets all attributes in BaseSignedSMIMEObject to their initial values. The
420    * attributes have the same values as when simple construcor is invoked. It
421    * means that after this method call, MIME message object is set to null, and
422    * it has to be rebuild again.
423    */

424   public void reset() {
425     super.reset();
426     this.ksArray.removeAllElements();
427     this.digestArray.removeAllElements();
428     this.including.removeAllElements();
429     this.certChainArray.removeAllElements();
430     this.privKeyArray.removeAllElements();
431     this.digestArray2.removeAllElements();
432     this.including2.removeAllElements();
433     this.aditionalCerts.removeAllElements();
434     this.capabilitiesTemp.removeAllElements();
435     this.capabilities.removeAllElements();
436     this.capabilities2.removeAllElements();
437   }
438
439
440 }
Popular Tags