public class EncryptedContent extends java.lang.Object implements SMimeContentType
S/MIME (Secure/Multipurpose Internet Mail Extensions) provides a consistent way to send and receive secure MIME data. Based on the popular Internet MIME standard, S/MIME provides the following cryptographic security services for electronic messaging applications: authentication, message integrity and non-repudiation of origin (using digital signatures) and privacy and data security (using encryption) (see S/MIME Version 3 Message Specification).
This class supports the creation and handling of S/MIME encrypted (enveloped)
messages in combination with the jakarta.mail architecture.
For creating and working with signed S/MIME messages, use the
SignedContent
class of the iaik.smime package.
S/MIME (Secure/Multipurpose Internet Mail Extensions) specifies the application/pkcs7-mime (smime-type "enveloped-data") type for data enveloping.
The whole (prepared) MIME entity to be enveloped into a CMS object of
type EnvelopedData which subsequently is inserted into an
application/pkcs7-mime MIME entity. The smime-type parameter for
enveloped messages is "enveloped-data", the file extension is ".p7m" (see
S/MIME Version 3 Message Specification). The "Content-" headers of a sample
message would look like:
Content-Type: application/pkcs7-mime; smime-type=enveloped-data;
name="smime.p7m"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7m"
rfvbn...
For creating a new EncryptedContent to be sent, first use a proper constructor,
and subsequently supply the content by means of a setContent, setText, or setDataHandler
method. Recipients are added by calling a proper addRecipient method,
depending on which CMS key management technique shall be used (key transport or
key agreement).
When setting the content encryption algorithm by means of the setEncryptionAlgorithm method, optionally
the key length may be specified. The
S/MIME Version 3 Message Specification recommends DES EDE3 CBC and RC2 CBC
to be used as content encryption algorithms. Only for the latter the key length has
a meaning and may specify 40, 68, or 128 (default) bits. Before actually sending the
Message with the encrypted content, the setHeaders method
shall be called for properly updating the message headers.
Typical usage (when using RSA key transport to be compatible to S/MIMEv2):
MimeMessage msg = new MimeMessage(session); ... EncryptedContent ec = new EncryptedContent(); // set the smime-type parameter to "enveloped-data" ec.setSMimeType(); ec.setContent(...); ec.addRecipient(recipientCertificate, AlgorithmID.rsaEncryption); ec.setEncryptionAlgorithm(algorithm, keyLength); // update message headers ec.setHeaders(msg); msg.setContent(ec, ec.getContentType()); Transport.send(msg);A recipient uses a proper
decryptSymmetricKey
method for decrypting the encrypted content encryption
key with her/his private key, and subsequently reads the content, e.g.:
EncryptedContent ec = (EncryptedContent)msg.getContent(); //recipient at index 0 decrypts the content encryption key: ec.decryptSymmetricKey(privateKey, 0); // get the content Object content = ec.getContent(); ... *For more information about the JakartaMail architecture, and how to parsing messages, consult Jakarta Mail specification.
For using the IAIK-JCE S/MIME classes, an application also may need the packages:
# Default mailcap file for the JakartaMail System # # for our content-handlers # text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed message/*;; x-java-content-handler=com.sun.mail.handlers.message_rfc822 # # IAIK 'mailcap' file # multipart/signed;; x-java-content-handler=iaik.smime.signed_content application/x-pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content application/x-pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content application/x-pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content application/pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content application/pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content application/pkcs10;; x-java-content-handler=iaik.smime.pkcs10_contentWhen creating a new EncryptedContent to be sent per default the new S/MIME content types (application/x-pkcs7-mime, application/x-pkcs7-signature) are used. For using the old types call the static
useNewContentTypes method of the SMimeParameters class before creating a new EncryptedContent
object, e.g.:
//switch to old content types SMimeParameters.useNewContentTypes(false); //create a SignedContent EncryptedContent sc = new EncryptedContent(); ...
SMimeEncryptedLOG| Constructor and Description |
|---|
EncryptedContent()
Creates a new EncryptedContent object.
|
EncryptedContent(jakarta.activation.DataSource dataSource)
Constructs a EncryptedContent object from the given data source.
|
EncryptedContent(SignedContent signedContent)
Creates a new S/MIME encrypted and signed content.
|
EncryptedContent(SMimeContentType smimeCT) |
| Modifier and Type | Method and Description |
|---|---|
void |
addRecipient(RecipientInfo recipientInfo)
Adds one recipient.
|
void |
addRecipient(X509Certificate recipientCertificate,
AlgorithmID keyEncAlg)
Adds one recipient.
|
void |
decryptSymmetricKey(KeyAndCertificateSource keyAndCertificateSource)
Locates one of user's decryption keys that is appropriate for decrypting one
of the content-encryption keys, decrypts the content-encryption key, and
prepares the cipher for decrypting the encrypted content.
|
void |
decryptSymmetricKey(java.security.Key recipientKey,
int recipientInfoIndex)
Uses the specified key for decrypting the content-encryption key to setup the
cipher for decrypting the encrypted content of this
EncryptedContent
object for the requesting recipient, specified by its recipientInfoIndex. |
void |
decryptSymmetricKey(java.security.Key recipientKey,
KeyIdentifier recipientIdentifier)
Uses the specified key for decrypting the content-encryption key to setup the
cipher for decrypting the encrypted content of this
EncryptedContent
object for the requesting recipient, specified by the given recipient identifier. |
void |
decryptSymmetricKey(java.security.Key recipientKey,
X509Certificate recipientCertificate)
Uses the specified key for decrypting the content-encryption key to setup the
cipher for decrypting the encrypted content of this
EncryptedContent
object for the requesting recipient, specified by the given recipient certificate. |
void |
decryptSymmetricKey(SecureStringBuffer password,
int recipientInfoIndex)
Uses the specified password to derive a key for decrypting the content-encryption key to setup the
cipher for decrypting the encrypted content of this
EncryptedContent
object for the requesting recipient, specified by its recipientInfoIndex. |
int |
decryptSymmetricKey(User user)
Locates one of user's decryption keys that is appropriate for decrypting one
of the content-encryption keys, decrypts the content-encryption key, and
prepares the cipher for decrypting the encrypted content.
|
java.lang.Object |
getContent()
Returns the content as a Java object.
|
java.io.InputStream |
getContentInputStream()
Returns an InputStream for this part's unparsed content.
|
java.lang.String |
getContentType()
Returns the ContentType and any attached parameters of this EncryptedObject.
|
jakarta.activation.DataHandler |
getDataHandler()
Return a DataHandler for the content within this part.
|
AlgorithmID |
getEncryptionAlgorithm()
Returns the content-encryption algorithm (including any associated parameters) of this
EncryptedContent.
|
java.io.InputStream |
getInputStream()
Returns an InputStream for this part's content.
|
int |
getRecipientInfoIndex(X509Certificate recipientCertificate)
Returns the recipient info index matching to the supplied recipient certificate.
|
RecipientInfo[] |
getRecipientInfos()
Returns information about all recipients of this message.
|
java.lang.String |
getSMimeType()
Returns the smime-type parameter to "enveloped-data".
|
void |
setBlockSize(int blockSize)
Sets the block size to use when encoding the content.
|
void |
setContent(jakarta.mail.Multipart multipart)
This method sets the given Multipart object as this EncryptedObject's content.
|
void |
setContent(java.lang.Object content,
java.lang.String type)
A convenience method for setting this EncryptedObject's content.
|
void |
setContentContentHeaders(jakarta.mail.Header[] headers)
Set some headers for the entity to be encrypted.
|
void |
setContentContentTransferEncoding(java.lang.String cte)
Sets the content transfer encoding of the entity to be encrypted.
|
void |
setDataHandler(jakarta.activation.DataHandler dataHandler)
Sets the content wrapped by a
jakarta.activation.DataHandler. |
void |
setEncryptionAlgorithm(AlgorithmID contentEncAlg,
int keyLength)
Sets the symmetric algorithm for encrypting the message.
|
void |
setHeaders(jakarta.mail.Part part)
Sets additional headers of the message containing this EncryptedContent.
|
void |
setSession(jakarta.mail.Session session)
Set the mail session to use when sending this message.
|
void |
setSMimeType()
Sets the smime-type parameter to "enveloped-data".
|
void |
setText(java.lang.String text)
A convenience method that sets the given String as this EncryptedObject's content
with a MIME type of "text/plain".
|
void |
writeTo(java.io.OutputStream os)
Writes this EncryptedContent DER encoded to the given output stream.
|
public EncryptedContent()
Use a proper setContent, setText, or
setDataHandler method for supplying the
content to be enveloped. Recipients are added by calling a proper
addRecipient method thereby specifying the recipient´s certificate,
and the key management algorithm to be used.
When setting the content encryption algorithm by means of the setEncryptionAlgorithm method, optionally
the key length may be specified. The
S/MIME Version 3 Message Specification recommends DES EDE3 CBC and RC2 CBC
to be used as content encryption algorithms. Only for the latter the key length has
a meaning and may specify 40, 68, or 128 (default) bits.
Before actually sending the Message with the encrypted content, the
setHeaders method shall be called for properly
updating the message headers.
Typical usage (for RSA key transport):
MimeMessage msg = new MimeMessage(session); ... EncryptedContent ec = new EncryptedContent(); ec.setContent(...); ec.addRecipient(recipientCertificate, AlgorithmID.rsaEncryption); ec.setEncryptionAlgorithm(algorithm, keyLength); ec.setHeaders(msg); msg.setContent(ec, ec.getContentType()); Transport.send(msg);When using this constructor the smime-type parameter will not be set. Use the
setSMimeType parameter for setting the
"enveloped-data" smime-type parameter.public EncryptedContent(SignedContent signedContent)
setSMimeType parameter for setting the
"enveloped-data" smime-type parameter.signedContent - the SignedContent as content of this EncryptedContentpublic EncryptedContent(SMimeContentType smimeCT) throws jakarta.mail.MessagingException
jakarta.mail.MessagingExceptionpublic EncryptedContent(jakarta.activation.DataSource dataSource)
throws java.io.IOException
encrypted_content supplying the data source.
For more information on data handling using the
jakarta.activation.DataSource for "MIME type based" data
access, see Jakarta EE´s
Jakarta Activation Framework (JAF) sepecification.
dataSource - the DataSource supplying the enveloped datajava.io.IOException - if an I/O error occurs during reading the objectpublic void setSMimeType()
public java.lang.String getSMimeType()
getSMimeType in interface SMimeContentTypepublic java.lang.String getContentType()
Message msg = ...; EncryptedContent ec = new EncryptedContent(); msg.setContent(ec, ec.getContentType()); ...
getContentType in interface SMimeContentTypepublic void setDataHandler(jakarta.activation.DataHandler dataHandler)
jakarta.activation.DataHandler.
This method provides the mechanism to set this EncryptedContent's content, e.g:
DataHandler dataHandler = new DataHandler(...); EncryptedContent sc = new EncryptedContent(); ec.setDataHandler(dataHandler);The DataHandler wraps around the actual content. It allows clients to discover the operations available on the content, and to instantiate the appropriate component to perform those operations. For more information consult Sun´s Jakarta Activation Framework (JAF) sepecification.
dataHandler - the DataHandler for the contentpublic void setContent(java.lang.Object content,
java.lang.String type)
Note that a DataContentHandler class for the specified type should be available to the JakartaMail implementation for this to work right; i.e., to do setContent(foobar, "application/x-foobar"), a DataContentHandler for "application/x-foobar" should be installed. Refer to the Jakarta Activation Framework for more information.
content - a java objecttype - MIME type of this objectpublic void setText(java.lang.String text)
text - the text that is the EncryptedObject's contentpublic void setContent(jakarta.mail.Multipart multipart)
multipart - the multipart object that is the EncryptedObject's contentpublic RecipientInfo[] getRecipientInfos()
public int getRecipientInfoIndex(X509Certificate recipientCertificate)
recipientCertificate - the certificate of the recipient-1 if no recipient info belonging to the given
certificate can be foundpublic void decryptSymmetricKey(java.security.Key recipientKey,
int recipientInfoIndex)
throws SMimeException,
java.security.InvalidKeyException
EncryptedContent
object for the requesting recipient, specified by its recipientInfoIndex.
This method first uses the given key for decrypting the encrypted
temporary symmetric key obtained from the corresponding RecipientInfo
structure, and subsequently uses this key to initialize a CipherInputStream for
decrypting the inherent encrypted content.
Note that the cipher will be only initialized for decrypting in this class. The
encrypted-content decryption actually is done during reading the data obtained by calling the
getInputStream, getContent,
or getDataHandler method.
So don´t call any of these methods before decrypting the encrypted content-encryption
key!
recipientInfos
field when using this method for decrypting the encrypted content-encryption key
and setting up the cipher for decryption. You may search for the index by using
the getRecipientInfoIndex method.
However, when having some recipient using a key agreement protocol the corresponding
RecipientInfo is of type KeyAgreeRecipientInfo
which may hold encrypted content-encryption keys for more than only one recipients
using the same key agreement algorithm with same domain parameters. Since this
decryptSymmetricKey method only can get the KeyAgreeRecipientInfo with
the given index (but not search for the right recipient in the KeyAgreeRecipientInfo), it
will step through any recipient included in the KeyAgreeRecipientInfo trying to
decrypt the encrypted content-encryption key with the supplied key. This may give
some overhead so it might be appropriate to use another decryptSymmetric method
allowing to immediately identify the particular recipient in mind by its
#decryptSymmetricKey(Key, KeyIdentifier) keyIdentifier} or certificate.
recipientKey - the key of the recipient to be used for decrypting the encrypted
content-encryption key for setting up the cipher for decrypting
the encrypted content-encryption key.recipientInfoIndex - the index into the recipientInfos fieldSMIMEException - if there occurs an error while decrypting the content-encryption key
or setting up the cipher for decrypting the contentjava.security.InvalidKeyException - if the specified key is not validSMimeExceptionpublic void decryptSymmetricKey(SecureStringBuffer password, int recipientInfoIndex) throws SMimeException, java.security.InvalidKeyException
EncryptedContent
object for the requesting recipient, specified by its recipientInfoIndex.
This method first uses the given password to derive a key for decrypting the encrypted
temporary symmetric key obtained from the corresponding RecipientInfo
structure, and subsequently uses this key to initialize a CipherInputStream for
decrypting the inherent encrypted content.
Note that the cipher will be only initialized for decrypting in this class. The
encrypted-content decryption actually is done during reading the data obtained by calling the
getInputStream, getContent,
or getDataHandler method.
So don´t call any of these methods before decrypting the encrypted content-encryption
key!
recipientInfos
field when using this method for decrypting the encrypted content-encryption key
and setting up the cipher for decryption. You may search for the index by using
the getRecipientInfoIndex method.
password - the password used to derive the key to be used for decrypting
the encrypted content-encryption key.recipientInfoIndex - the index into the recipientInfos fieldSMIMEException - if there occurs an error while decrypting the content-encryption key
or setting up the cipher for decrypting the contentjava.security.InvalidKeyException - if the specified key is not validSMimeExceptionpublic void decryptSymmetricKey(java.security.Key recipientKey,
KeyIdentifier recipientIdentifier)
throws SMimeException,
java.security.InvalidKeyException
EncryptedContent
object for the requesting recipient, specified by the given recipient identifier.
This method first uses the given key for decrypting the encrypted
temporary symmetric key obtained from the corresponding RecipientInfo
structure, and subsequently uses this key to initialize a CipherInputStream for
decrypting the inherent encrypted content.
Note that the cipher will be only initialized for decrypting in this class. The
encrypted-content decryption actually is done during reading the data obtained by calling the
getInputStream, getContent,
or getDataHandler method.
So don´t call any of these methods before decrypting the encrypted content-encryption
key!
This decryptSymmetricKey method can be used to decrypt the encrypted
content-encryption key and setup the cipher for decryption for
any type of RecipientInfo. The supplied recipient identifier will be used for
searching for the right RecipientInfo in the recipientInfos field.
recipientKey - the key of the recipient to be used for decrypting
the encrypted content-encryption key for setting up the cipher for decrypting
the encrypted content-encryption key.recipientIdentifier - specifies which RecipientInfo the given key belongs toSMIMEException - if there occurs an error while decrypting the content-encryption key
or setting up the cipher for decrypting the content, or no RecipientInfo
for the requested recipient is includedjava.security.InvalidKeyException - if the specified key is not validSMimeExceptionpublic void decryptSymmetricKey(java.security.Key recipientKey,
X509Certificate recipientCertificate)
throws SMimeException,
java.security.InvalidKeyException
EncryptedContent
object for the requesting recipient, specified by the given recipient certificate.
This method first uses the given key for decrypting the encrypted
temporary symmetric key obtained from the corresponding RecipientInfo
structure, and subsequently uses this key to initialize a CipherInputStream for
decrypting the inherent encrypted content.
Note that the cipher will be only initialized for decrypting in this class. The
encrypted-content decryption actually is done during during reading the data obtained by calling the
getInputStream, getContent,
or getDataHandler method.
So don´t call any of these methods before decrypting the encrypted content-encryption
key!
Note that this method only can be used for decrypting the encrypted content
encyrption key and setting up the cipher for content decryption if the recipient
in mind has a RecipientInfo of type KeyTransRecipientInfo or KeyAgreeRecipientInfo using a public
key from a certificate for its key management protocol. However, this should be
no problem since S/MIME generally only uses certificate based RecipientInfos.
recipientKey - the key of the recipient to be used for decrypting
the encrypted content-encryption key for setting up the cipher for decrypting
the encrypted content-encryption key.recipientCertificate - the certificate of the recipient specifying which
RecipientInfo the recipient´s private key belongs toSMimeException - if there occurs an error while decrypting the content-encryption key
or setting up the cipher for decrypting the content, or no RecipientInfo
for the requested recipient is includedjava.security.InvalidKeyException - if the specified recipient key is not validpublic int decryptSymmetricKey(User user) throws UserNotLoggedInException, NotARecipientException, SMimeException
The cipher will be only initialized for decrypting with this call; The
encrypted-content decryption actually is done when the data is read by
calling the getInputStream,
getContent, or getDataHandler
method. So don´t call any of these methods before decrypting the encrypted
content-encryption key!
KeyTransRecipientInfo)
format and contains the key identifier in 'issuerAndSerialNumber'
(IssuerAndSerialNumber) format; all other formats
of recipient information are ignored.user - the userUserNotLoggedInException - if the user is not logged inNotARecipientException - if the user is not listed as a recipient (unable to decrypt the content)SMimeException - if an error occurs while decrypting the content-encryption key or
setting up the cipher for decrypting the contentpublic void decryptSymmetricKey(KeyAndCertificateSource keyAndCertificateSource) throws NotARecipientException, SMimeException
The cipher will be only initialized for decrypting with this call; The
encrypted-content decryption actually is done when the data is read by
calling the getInputStream,
getContent, or getDataHandler
method. So don´t call any of these methods before decrypting the encrypted
content-encryption key!
KeyTransRecipientInfo)
format and contains the key identifier in 'issuerAndSerialNumber'
(IssuerAndSerialNumber) format; all other formats
of recipient information are ignored.keyAndCertificateSource - a user's keys and certificatesNotARecipientException - if the user is not listed as a recipient (unable to decrypt the content)SMimeException - if an error occurs while decrypting the content-encryption key or
setting up the cipher for decrypting the contentpublic void setHeaders(jakarta.mail.Part part)
Content-Disposition: attachment";
filename="smime.p7m"
Content-Transfer-Encoding: base64
setHeaders in interface SMimeContentTypepart - message to add the headerspublic void setBlockSize(int blockSize)
The default block size is 2048.
blockSize - the block size to use when encoding the content.public java.lang.Object getContent()
throws java.io.IOException,
jakarta.mail.MessagingException
java.io.IOException - if an I/O error occurs when getting the content from the inherent data handlerjakarta.mail.MessagingException - if an error occurs when fetching the inherent data handlerpublic jakarta.activation.DataHandler getDataHandler()
throws jakarta.mail.MessagingException
jakarta.mail.MessagingException - if an error occurs when fetching the data handlerpublic java.io.InputStream getInputStream()
throws java.io.IOException,
jakarta.mail.MessagingException
java.io.IOException - if an I/O error occurs when getting the input stream from the inherent data handlerjakarta.mail.MessagingException - if an error occurs when fetching the inherent data handlerpublic java.io.InputStream getContentInputStream()
throws java.io.IOException
This method can be used to get the content of large messages.
java.io.IOExceptionpublic void addRecipient(X509Certificate recipientCertificate, AlgorithmID keyEncAlg)
When using this method for adding a Recipient, the corresponding
RecipientInfo will be the KeyTransRecipientInfo choice and the recipient certificate will
be identified by IssuerAndSerialNumber. So use this method with rsaEncyrption
as key transport algorithm to be compatible to S/MIMEv2.
recipientCertificate - the certificate of the recipientkeyEncAlg - the algorithm to use for encrypting the symmetric key
(e.g. AlgorithmID.rsaEncryption)public void addRecipient(RecipientInfo recipientInfo)
recipientInfo - the recipientInfo for the recipient to be addedpublic void setEncryptionAlgorithm(AlgorithmID contentEncAlg, int keyLength)
The default value is AlgorithmID.des_EDE3_CBC
Note: The keylength should correspond to the keylength of the
selected AlgorithmID. For example, if AlgorithmID.aes_256_CBC
is selected, but a keylength of 128 is used, then an AES key of
length 128 will be generated. However, the algorithm ID used will
contain the Object ID for the incorrect algorithm keysize. So although the
message will be generated, this will likely result in a decryption failure
at the recipient's end.
contentEncAlg - the algorithm for encrypting the contentkeyLength - the key length for RC2public AlgorithmID getEncryptionAlgorithm()
public void setContentContentTransferEncoding(java.lang.String cte)
setText or
setDataHandler is used for
supplying the content. However, the supplied content transfer
encoding will be ignored when the inner entity is a structured
entity.cte - the content transfer encoding to be applied to the
inner entity to be signedpublic void setContentContentHeaders(jakarta.mail.Header[] headers)
setText or
setDataHandler is used for
supplying the content, or a SignedContent is being encrypted.
However, the supplied header will be ignored
when the inner entity is a structured entity. The supplied headers
are not cloned.headers - the headers to be applied to the
inner entity to be signedpublic void setSession(jakarta.mail.Session session)
session - public void writeTo(java.io.OutputStream os)
throws java.io.IOException,
jakarta.mail.MessagingException
java.io.IOException - if an error occurs writing to the streamjakarta.mail.MessagingException - if an error occurs when fetching the data to be written