public class SMimeEncrypted extends EnvelopedDataStream
S/MIME v3 (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...
This class extends the EnvelopedDataStream
class of the iaik.cms or taking advantage of the stream architecture
introduced there. Following this practice, the data is prepared according
CMS (Cryptographic Message Syntax) by piping it through a cipher stream for performing the content
encryption.
The steps for creating a SMimeEncrypted object and writing it to a stream may be summarized as follows (note that in this example we use Triple DES as content encryption algorithm and RSA key transport for encrypting the content-encryption key; however, an application may wish to use any other content encryption algorithm supported by a cryptographic provider installed, and any other key management technique allowed (e.g. ESDH key agreement):
InputStream data_stream = ...;
AlgorithmID contentEA = AlgorithmID.des_CBC;
SMimeEncrypted sme = new SMimeEncryoted(data_stream, contentEA, -1);
This step also will create the symmetric content encryption key.
addRecipient method thereby
specfying the particular recipient´s certificate and setting the RSA
encryption method to be used for encrypting the symmetric content encryption
key with the recipient´s public key obtained from the supplied certificate, e.g.:
sme.addRecipient(recipientCert1, AlgorithmID.rsaEncryption);
sme.addRecipient(recipientCert2, AlgorithmID.rsaEncryption);
writeTo method for wrapping
the EnvelopedData object into a ContentInfo and writing it BER encoded to an
output stream thereby actually performing the content encryption by piping the
data through a cipher stream:
OutputStrem os = ...;
sme.writeTo(os);
creates
a new SMimeEncrypted object from an input stream supplying the BER encoded
message, subsequently decrypts the
encrypted symmetric content encryption key with its private key, and finally gets and reads the data holding input stream which is decrypted
during the read operation, e.g.:
InputStream enveloped_stream = ...;
SMimeEncrypted sme = new SMimeEncrypted(encrypted_stream);
//recipient has index 0
sme.decryptSymmetricKey(privateKey, 0);
//get and read the data
InputStream data_stream = sme.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
blockSize_, encryptedContentInfo_, m_envelopedData, originatorInfo_, recipientInfos_, symmetricKey_, unprotectedAttrs_, version_| Constructor and Description |
|---|
SMimeEncrypted(java.io.InputStream is)
Creates a new SMimeEncrypted object where the BER encoded message is read
from the given input stream.
|
SMimeEncrypted(java.io.InputStream is,
AlgorithmID contentEA,
int keyLength)
Creates a new SMimeEncrypted object where the data to be enveloped is read
from the given InputStream.
|
| Modifier and Type | Method and Description |
|---|---|
void |
addRecipient(X509Certificate recipientCertificate,
AlgorithmID keyEA)
Adds one recipient to this S/MIME EnvelopedData object.
|
void |
decode(java.io.InputStream is)
Reads and decodes the enveloped message from an input stream.
|
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
SMimeEncrypted
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
SMimeEncrypted
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
SMimeEncrypted
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
SMimeEncrypted
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.
|
AlgorithmID |
getEncryptionAlgorithm()
Returns the content-encryption algorithm (including any associated
parameters) of this SMimeEncrypted object.
|
int |
getRecipientInfoIndex(X509Certificate recipientCertificate)
Returns the recipient info index matching to the supplied recipient certificate.
|
ASN1Object |
toASN1Object()
Returns the S/MIME enveloped message as an ASN1Object.
|
void |
writeTo(java.io.OutputStream os)
Writes this SMimeEncrypted object to the supplied output stream.
|
void |
writeTo(java.io.OutputStream os,
int blockSize)
Writes this SMimeEncrypted object to the supplied output stream.
|
addRecipientInfo, getBlockSize, getContentType, getEncryptedContentInfo, getInputStream, getOriginatorInfo, getRecipientInfo, getRecipientInfo, getRecipientInfos, getUnprotectedAttribute, getUnprotectedAttributes, getVersion, notifyEOF, setBlockSize, setOriginatorInfo, setRecipientInfos, setUnprotectedAttributes, setupCipher, setupCipher, setupCipher, setupCipher, setupCipher, setupCipher, toASN1Object, toString, toStringpublic SMimeEncrypted(java.io.InputStream is,
AlgorithmID contentEA,
int keyLength)
throws java.security.NoSuchAlgorithmException
This constructor automatically will create the symmetric content encryption key for the specified algorithm.
is - an InputStream holding the data to be envelopedcontentEA - the content encryption algorithm to be usedkeyLength - the length of the key; undefined values set the
default key length for the specified algorithm (e.g. 128 for RC2)java.security.NoSuchAlgorithmException - if there is no implementation for the specified algorithmpublic SMimeEncrypted(java.io.InputStream is)
throws java.io.IOException
Do not use this constructor for supplying the content data
to be enveloped. This constructor may be used by the recipient for parsing an
already exisiting SMimeEncrypted object, supplied as BER encoding
from an input stream, that may have been created by means of the
writeTo method.
Use the SMimeEncrypted(InputStream is, AlgorithmID contentEA, int keyLength)
constructor for supplying the content data to be enveloped when creating a
SMimeEncrypted object.
is - the input stream where the BER encoded message shall be read fromjava.io.IOException - if an I/O error occurspublic void decode(java.io.InputStream is)
throws java.io.IOException
decode in interface ContentStreamdecode in class EnvelopedDataStreamis - the InputStream holding a BER encoded SMimeEncrypted objectjava.io.IOException - if an I/O error occurs during reading from the InputStreampublic 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
SMimeEncrypted
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 method. So don´t call
getInputStream 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 decryptSymmetricKey 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.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 recipient key is not validSMimeExceptionpublic void decryptSymmetricKey(SecureStringBuffer password, int recipientInfoIndex) throws SMimeException, java.security.InvalidKeyException
SMimeEncrypted
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 method. So don´t call
getInputStream 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 recipient key is not validSMimeExceptionpublic void decryptSymmetricKey(java.security.Key recipientKey,
KeyIdentifier recipientIdentifier)
throws SMimeException,
java.security.InvalidKeyException
SMimeEncrypted
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 method. So don´t call
getInputStream 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.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 recipient key is not validSMimeExceptionpublic void decryptSymmetricKey(java.security.Key recipientKey,
X509Certificate recipientCertificate)
throws SMimeException,
java.security.InvalidKeyException
SMimeEncrypted
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 reading the data obtained by calling the
getInputStream method. So don´t call
getInputStream 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.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 method. So don´t call
this method 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 method. So don´t call
this method 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 addRecipient(X509Certificate recipientCertificate, AlgorithmID keyEA) throws SMimeException
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 recipientkeyEA - the algorithm to use for encrypting the symmetric key
(e.g. AlgorithmID.rsaEncryption)SMimeException - if it was not possible to encrypt the symmetric key for this recipientpublic AlgorithmID getEncryptionAlgorithm()
public ASN1Object toASN1Object() throws CMSException
toASN1Object in interface ContentStreamtoASN1Object in class EnvelopedDataStreamCMSException - if an error occurs while building the
ASN.1 objectpublic void writeTo(java.io.OutputStream os)
throws java.io.IOException
writeTo in class EnvelopedDataStreamos - the output stream to which this SMimeEncrypted shall be writtenjava.io.IOException - if an I/O error occurs while writing to the streampublic void writeTo(java.io.OutputStream os,
int blockSize)
throws java.io.IOException
blockSize parameter indicates the block size to
be used for performimg block encoding.writeTo in class EnvelopedDataStreamos - the output stream to which this SMimeEncrypted shall be writtenblockSize - the block size for using block encodingjava.io.IOException - if an I/O error occurs while writing to the stream