001: /*
002: * Title: Oyster Project
003: * Description: S/MIME email sending capabilities
004: * @Author Vladimir Radisic
005: * @Version 2.1.6
006: */
007:
008: package org.enhydra.oyster.activation;
009:
010: import org.enhydra.oyster.crypto.SymmetricEncryption;
011: import org.enhydra.oyster.cms.*;
012: import org.enhydra.oyster.util.MimeAssist;
013: import org.enhydra.oyster.util.MimeAssist;
014: import org.enhydra.oyster.exception.SMIMEException;
015: import org.enhydra.oyster.exception.SMIMEIOException;
016: import javax.mail.internet.MimeMessage;
017: import java.security.cert.X509Certificate;
018: import javax.activation.DataSource;
019: import java.io.*;
020:
021: /**
022: * CMSEnvelopedDataSource represents implementation of DataSource interfaces. It
023: * is used within MimeMessage as a source of data. Also, object of this class is
024: * used to create DER encoded Cryptographic Message Syntax (CMS) object
025: * represented in ASN.1 notation according to RFC2630. This object (CMS) is used
026: * as the source of data for MimeMessage in the process of sending encrypted message.
027: */
028: public class CMSEnvelopedDataSource implements DataSource {
029:
030: /**
031: * Container for encrypted content information
032: */
033: private EncryptedContentInfo encContInf;
034:
035: /**
036: * Container for RecipientInfos
037: */
038: private RecipientInfos recInf;
039:
040: /**
041: * Constructs CMS object for encryption with MIME Message in form of
042: * byte array and with given values for encryption algorithm.
043: * @param message0 message for encryption
044: * @param algType0 given symmetric algorithm for encryption
045: * @param keyLength0 key length in bits
046: * @exception SMIMEException in case of unrecognized type of symmetryc
047: * algorithm or invalid key length. Also, it can be caused by problems in
048: * construction or work with some inner objects instantiated from classes
049: * that belong to org.enhydra.oyster.der or org.enhydra.oyster.cms
050: * packages used in other CMSEnvelopedDataSource constructor.
051: */
052: public CMSEnvelopedDataSource(byte[] message0, String algType0,
053: int keyLength0) throws SMIMEException {
054: encContInf = new EncryptedContentInfo();
055: SymmetricEncryption symEnc = new SymmetricEncryption(algType0,
056: keyLength0); // Engine for symmetric encryption - setting symetric algorythm type and algorythm parameters (key length)
057: symEnc.encrypt(message0); // algType0 can be one of following strings (representing symetric algorithm type): "DESede","RC2","DES"
058: Content encryptedContent = new Content(symEnc
059: .getEncryptedValue(), false); // Creating the Encrypted Content
060: AlgorithmIdentifier contentEncryptAlgID;
061: if (algType0.equalsIgnoreCase("RC2_CBC")) // Using RC2 algorithm and appropriate parameter
062: {
063: contentEncryptAlgID = new AlgorithmIdentifier("RC2_CBC",
064: "NAME_STRING");
065: RC2CBCParameter par = new RC2CBCParameter(symEnc
066: .getKeyLength(), symEnc.getIV());
067: contentEncryptAlgID.addParamToAlgorithmId(par
068: .getDEREncoded()); // Creating the Content Encryption Algorithm Identifier
069: } else if (algType0.equalsIgnoreCase("DES_EDE3_CBC")) // Using DES EDE3 algorithm and appropriate parameter
070: {
071: contentEncryptAlgID = new AlgorithmIdentifier(
072: "DES_EDE3_CBC", "NAME_STRING");
073: DESede3CBCParameter par = new DESede3CBCParameter(symEnc
074: .getIV());
075: contentEncryptAlgID.addParamToAlgorithmId(par
076: .getDEREncoded()); // Creating the Content Encryption Algorithm Identifier
077: } else if (algType0.equalsIgnoreCase("DES")) // Using DES algorithm and appropriate parameter
078: {
079: contentEncryptAlgID = new AlgorithmIdentifier("DES",
080: "NAME_STRING");
081: DESede3CBCParameter par = new DESede3CBCParameter(symEnc
082: .getIV()); // Same parameter as for DES EDE algorithm
083: contentEncryptAlgID.addParamToAlgorithmId(par
084: .getDEREncoded()); // Creating the Content Encryption Algorithm Identifier
085: } else
086: throw new SMIMEException(1013);
087: ContentTypeIdentifier contentData = new ContentTypeIdentifier(
088: "ID_DATA", "NAME_STRING"); // Creating the Content Type
089: encContInf.addContentType(contentData.getDEREncoded());
090: encContInf.addEncryptAlgorithmID(contentEncryptAlgID
091: .getDEREncoded());
092: encContInf.addEncryptContent(encryptedContent.getDEREncoded());
093: recInf = new RecipientInfos(symEnc.getSymmetricKey()); // Initialization of Recipient Infos with RC2 symetric key
094: }
095:
096: /**
097: * Constructs CMS object for encryption with MIME Message in form of
098: * instance of MimeMessage class and with defined values for encryption algorithm.
099: * @param message0 message for encryption
100: * @param algType0 given symmetric algorithm for encryption
101: * @param keyLength0 key length in bits
102: * @exception SMIMEException in case of unrecognized type of symmetryc
103: * algorithm, invalid key length or in case of failure in MimeMessageConvertor
104: * class which performes transformation from MimeMessage object to byte array.
105: * Also, it can be caused by problems in construction or work with some
106: * inner objects instantiated from classes that belong to
107: * org.enhydra.oyster.der or org.enhydra.oyster.cms packages used
108: * in other CMSEnvelopedDataSource constructor.
109: */
110: public CMSEnvelopedDataSource(MimeMessage message0,
111: String algType0, int keyLength0) throws SMIMEException {
112: this (MimeAssist.messageConvertor(message0), algType0,
113: keyLength0);
114: }
115:
116: /**
117: * Adds recipient. This method must be performed at least once.
118: * @param cert0 recipient's X509Certificate (.cer file).
119: * @exception SMIMEException caused by addRecipient method of inner object
120: * which is instance of class RecipientInfos.
121: */
122: public void addRecipient(X509Certificate cert0)
123: throws SMIMEException {
124: recInf.addRecipient(cert0);
125: }
126:
127: /**
128: * Returns complete DER encoded CMS Enveloped Object.
129: * @return DER encoded CMS Enveloped Object represented as byte array
130: * @exception SMIMEException caused by problems in construction or work
131: * with some inner objects instantiated from classes that belong to
132: * org.enhydra.oyster.der or org.enhydra.oyster.cms packages.
133: */
134: public byte[] getCMSEnvelopedObject() throws SMIMEException {
135: ContentTypeIdentifier contentTypeEnvelopDataId = new ContentTypeIdentifier(
136: "ID_ENVELOPEDDATA", "NAME_STRING"); // Creating the Content Type
137: EnvelopedData envData = new EnvelopedData(); // Container for enveloped data sub object
138: envData.addCMSVersion(new CMSVersion(0).getDEREncoded());
139: envData.addRecipientInfos(recInf.getDEREncoded());
140: envData.addEncryptContentInfo(encContInf.getDEREncoded());
141: Content cont = new Content(envData.getDEREncoded(), true); // Filling enveloped data content in context specific DER object
142: ContentInfo cmsObjectEnvelopedData = new ContentInfo();
143: cmsObjectEnvelopedData.addContentType(contentTypeEnvelopDataId
144: .getDEREncoded());
145: cmsObjectEnvelopedData.addContent(cont.getDEREncoded());
146: return cmsObjectEnvelopedData.getDEREncoded();
147: }
148:
149: /**
150: * Returns complete DER encoded CMS Enveloped Object with BASE64 encoding
151: * @return DER encoded CMS Enveloped Object represented as byte array with
152: * performed BASE64 encoding
153: * @exception SMIMEException in case of failure in Base64 encoding performed
154: * on the generated SMIME message byte array by Base64ForMime class. Also, it
155: * can be caused by problems in construction or work with some inner objects
156: * instantiated from classes that belong to org.enhydra.oyster.der or
157: * org.enhydra.oyster.cms packages used in getCMSEnvelopedObject() method.
158: */
159: public byte[] getBASE64CMSEnvelopedObject() throws SMIMEException {
160: return MimeAssist.getBASE64WithBreakOn76(this
161: .getCMSEnvelopedObject());
162: }
163:
164: /**
165: * Implements getContentType method from DataSource interface
166: * @return Content-Type for MIME message header field
167: */
168: public String getContentType() {
169: // For new version of mail clients: "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"";
170: return "application/x-pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"";
171: }
172:
173: /**
174: * Implements getInputStream method from DataSource interface
175: * @return CMS enveloped object
176: * @exception SMIMEIOException thrown as result of SMIMEException
177: */
178: public InputStream getInputStream() throws SMIMEIOException {
179: try {
180: return new ByteArrayInputStream(getCMSEnvelopedObject());
181: } catch (SMIMEException e) {
182: throw new SMIMEIOException(e);
183: }
184: }
185:
186: /**
187: * ImplementS getName method from DataSource interface
188: * @return Name: EnvelopedDataContentInfo
189: */
190: public String getName() {
191: return "EnvelopedDataContentInfo";
192: }
193:
194: /**
195: * Implements getOutputStream method from DataSource interface. This method is
196: * not in use.
197: * @return nothing
198: * @exception IOException is always thrown when this method is used.
199: */
200: public OutputStream getOutputStream() throws IOException {
201: throw new IOException(
202: "EnvelopedDataContentInfo does not support getOutputStream()");
203: }
204: }
|