iaik.smime
Class SignedContent

java.lang.Object
  extended by javax.mail.Multipart
      extended by javax.mail.internet.MimeMultipart
          extended by iaik.smime.SignedContent
All Implemented Interfaces:
CryptoContent, EOFListener, java.util.EventListener

public class SignedContent
extends javax.mail.internet.MimeMultipart
implements CryptoContent, EOFListener

This class can be used to create and parse signed S/MIME emails in combination with the javax.mail package.

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 (RFC 2045), 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 creation, handling and parsing of signed S/MIME messages in combination with the javax.mail architecture. For creating, parsing and working with encrypted S/MIME messages, use the EncryptedContent class of the iaik.smime package.

S/MIME provides two formats for signed messages:

The first format (application/pkcs7-mime and signed-data) packs the whole (prepared) MIME entity to be signed into a CMS ( RFC 5652) SignedData object which subsequently is inserted into an application/pkcs7-mime MIME entity. The smime-type parameter for messages signed using this format is "signed-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="signed-data";
     name="smime.p7m"
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment;
     filename="smime.p7m"

 fgwehds...

 
For viewing a message that is signed using this format, a recipient must take care for a S/MIME aware mail client.

The second format (multipart/signed) creates a MIME entity that consists of two parts. The first part contains the MIME entity to be signed, and the second part contains the signature, which is a CMS ( RFC 5652) detached signature, inserted into a MIME entity of type application/pkcs7-signature (or application/x-pkcs7-signature for early implementations) leaving the EncapsulatedContentInfo (content) field of the SignedData object empty. The multipart/signed Content type requires two parameters (see S/MIME Version 3 Message Specification):

The "Content-" headers of a sample message would look like:
 Content-Type: multipart/signed;
     protocol="application/pkcs7-signature";
     micalg=sha1;
     boundary="----=_NextPart_000_00AA_01BD7FE8.1CD08610"

 ------_NextPart_000_00AA_01BD7FE8.1CD08610
 Content-Type: text/plain  ;
     charset="iso-8859-1"
 Content-Transfer-Encoding: 8bit

 This is a clear-signed message.

 ------_NextPart_000_00AA_01BD7FE8.1CD08610
 Content-Type: application/pkcs7-signature;
     name=smime.p7s
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment;
     filename=smime.p7s

 sdefqj...

 ------_NextPart_000_00AA_01BD7FE8.1CD08610--
 
Messages signed using this format can be viewed by the recipient, regardless of being equipped with S/MIME aware software.


This class supports both formats, application/x-pkcs7-mime and multipart/signed. For distinguishing between the two formats when creating a new SignedContent object using the SignedContent(boolean implicit) constructor, the implicit parameter has to be set either to true or to false, depending on whether to use the application/pkcs7-mime format (implicit = true), or the multipart/signed format (implicit = false):

 SignedContent sc = new SignedContent(true);
   
  or

 SignedContent sc = new SignedContent(false);
 

When creating an implicit message you also may wish to set the smime-type parameter to signed-data or certs-only, depending on what kind of message to be sent:

 SignedContent sc = new SignedContent(true, SignedContent.SIGNED_DATA);
 
respectively
 SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
 
An application/pkcs7-mime message of type "certs-only" does not calculate a signature; it only may be used to disseminate certificates by using the degenarate "signature-less" variant of the CMS SignedData type.

For creating a signed message to be sent using the features of the MIME implementing javax.mail.internet package of the JavaMail API, first create a (either implicit or explicit) SignedContent object, supply the content and sign it with your private key. Subsequently put this SignedContent object into a javax.mail.internet.MimeMessage by calling a proper setContent method. Finally the message is sent by calling Transport.send(msg), e.g.:

 // create an explicit signed message (content-type "multipart/signed")
 boolean implicit = false;
 SignedContent sc = new SignedContent(implicit);
 // set the content to be signed
 sc.setContent(...);
 // set the sender certificates; may also contain the encryption cert of the sender
 sc.setCertificates(certificates);
 // set the private key of the signer, identified by the corresponding certificate
 sc.addSigner(privateKey, signerCertificate);
 ...
 // create a MimeMessage object for the current mail session
 MimeMessage msg = new MimeMessage(session);
 ...
 // set sender, recipient(s), subject, ...
 ...
 // set the signed content
 msg.setContent(sc, sc.getContentType());
 // send the message
 Transport.send(msg);
 
When using method addSigner(signerKey, signerCertificate) to supply the signer information like in the sample above, digest and signature algorithm will be automatically calculated from the private key algorithm. If you want to explicitly set digest/signature algorithm you may call some alternative addSigner method).

When creating an implicit SignedContent object for sending a message of type application/pkcs7-mime, it is highly recommended to call method setHeaders before calling Transport.send in order to set some headers (Content-Transfer-Encoding, Content-Disposition) for the message containing the SignedContent:

 boolean implicit = true;
 SignedContent sc = new SignedContent(implicit);
 ...
 MimeMessage msg = new MimeMessage(session);
 ...
 // set the signed content
 msg.setContent(sc, sc.getContentType());
 // let the SignedContent update some message headers
 sc.setHeaders(msg);
 // send the message
 Transport.send(msg);
 
If method setHeaders is not called, JavaMail may run method writeTo twice to itself determine the content transfer encoding to be used.

The recipient verifies a S/MIME signed message by calling a proper verify method, depending on whether the signer certificate list is included in the received message or not, and/or if there more than only one signers on the content. If certificates are not included, the signer certificate or public key has to be explicitly supplied when calling a corresponding verify method. When certificates are included, the verify method returns the signer certificate if the verification process turns out that the signature is correct. If the verification process fails, a SignatureException is thrown, e.g.:

 // the message to be parsed
 MimeMessage msg = ...;
 // get the SignedContent
 SignedContent sc = (SignedContent)msg.getContent();
 try {
    X509Certificate signer = sc.verify();
    System.out.println("This message is signed from: "+signer.getSubjectDN());
 } catch (java.security.SignatureException ex) {
    ...
 }
 // get the content:
 Object content = sc.getContent();
 ...
 
For more information about the JavaMail architecture, consult the JavaMail specification. Note, that JavaMail uses the JavaBeans Activation Framework (JAF) for encapsulating the message data. To confirm with the JAF, this class also supports a setDataHandler method for supplying the content to be signed, wrapped by a javax.activation.DataHandler, e.g.:
 MimeBodyPart mbp1 = new SMimeBodyPart();
 mbp1.setText("Please find our offer as attached to this message!\n\n");
 MimeBodyPart mbp2 = new SMimeBodyPart();
 mbp2.setDataHandler(new DataHandler(new FileDataSource("C:/temp/offer.doc")));
 mbp2.setFileName("offer.doc");
 Multipart mp = new SMimeMultipart();
 mp.addBodyPart(mbp1);
 mp.addBodyPart(mbp2);
 DataHandler dataHandler = new DataHandler(mp, mp.getContentType());
 SignedContent sc = new SignedContent(false);
 sc.setDataHandler(dataHandler);
 sc.setCertificates(certificates);
 sc.addSigner(privateKey, signerCertificate);
 ...
 MimeMessage msg = new MimeMessage(session);
 ...
 set sender, recipient(s), subject, ...
 ...
 msg.setContent(sc, sc.getContentType());
 Transport.send(msg);
 
Notice, that when creating a multipart/signed message as above, body parts and multiparts have to be supplied as instances of SMimeBodyPart and SMimeMultipart for ensuring a proper canonicalization. This is especially required when creating an explicit signed message (content-type multipart/signed) because in this case the content is not encapsulated (and thus transfer-protected) by the SignedData object. For that reason, IAIK-CMS checks if SMimeBodyParts and SMimeMultiparts are used for explicit signed messages and throws an exception if common MimeBodyParts and MimeMultiparts are used, e.g.:

"Please use SMimeMultipart instead of MimeMultipart!"

However, the SMimeBodyPart/SMimeMultipart check maybe turned off for some particular SignedContent object by calling method checkForSMimeParts:

 boolean implicit = false;
 SignedContent sc = new SignedContent(implicit);
 // do not check for usage of SMimeBodyParts/SMimeMultiparts
 sc.checkForSMimeParts(false);
 ...
 
This may be useful when supplying the to-be-signed content from an already existing (and therefore properly canonicalized/encoded) message. The SMimeBodyPart/SMimeMultipart also can be generally turned off by calling the static method setCheckForSMimeParts of class SMimeParameters:
 SMimeParameters.setCheckForSMimeParts(false);
 

Additional setContent (or setText) methods provide alternative ways for supplying the content, which then internally is wrapped by a data handler, e.g.:

 SignedContent sc = new SignedContent(true);
 sc.setText("Immediately supplied text/plain data which internally will be wrapped by a data handler");
 
When creating a application/pkcs7-mime message of type certs-only for sending certificates/crls only, no content has to be supplied at all:
  SignedContent sc = new SignedContent(true, SignedContent.CERTS_ONLY);
  sc.setCertificates(certificates);
  msg.setContent(sc, sc.getContentType());
  //set filename and attachment parameters
  sc.setHeaders(msg);
 ...
 
For more information about the JavaMail architecture, and how to handling MIME messages, consult the JavaMail specification.

For using the IAIK-CMS S/MIME library, you also will need the following packages:

The JAF assignment between MIME-types and content handlers is done by means of a RFC 1524 mailcap file which is included in the IAIK-CMS distribution. It defines the following classes as content handlers for the corresponding MIME types:
 #
 # IAIK 'mailcap' file entries
 #
 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_content
 
The content handlers are registered by copying the mailcap file into the lib directory of your JDK (/lib). Alternatively you may register the IAIK-S/MIME mailcap file dynamically by using the default command map:
 String mailcapFileName = ...;
 MailcapCommandMap mc = new MailcapCommandMap(mailcapFileName);
 CommandMap.setDefaultCommandMap(mc);
 
Or you may add the IAIK mailcap entries to the default mailcap command map, e.g.:
 MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
 mc.addMailcap("multipart/signed;; x-java-content-handler=iaik.smime.signed_content");
 mc.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content");
 mc.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content");
 mc.addMailcap("application/pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content");
 mc.addMailcap("application/pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content");
 mc.addMailcap("application/x-pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content");
 mc.addMailcap("application/pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content");
 CommandMap.setDefaultCommandMap(mc);
 
For a more detailed description of mailcap handling consult the Javadoc of the Activation Framework.

When creating a new SignedContent to be sent, per default the new S/MIME content typs (application/pkcs7-mime, application/pkcs7-signature) are used. For using the old types (application/x-pkcs7-mime, application/x-pkcs7-signature) call the static useNewContentTypes method of the SMimeParameters class before creating a new SignedContent object, e.g.:

 //switch to old content types
 SMimeParameters.useNewContentTypes(false);
 //create a SignedContent
 boolean implicit = ...;
 SignedContent sc = new SignedContent(implicit);
 ...
 

Attention! This class is extended from class javax.mail.MimeMultipart but does not offer (and override) all methods of class MimeMultipart (e.g. methods like addBodyPart, getBodyPart,... are not supported). Extension from class MimeMultipart is necessary to fit in the JavaMail framework, however currently not all methods can be supported because of one-pass parsing facilities. For that reason an application shall use only those methods that are provided by class SignedContent itself.

See Also:
SMimeSigned, JMailSMimeSigned, EncryptedContent, SignedContent

Field Summary
static java.lang.String CERTS_ONLY
          SMime-type "certs-only".
static java.lang.String SIGNED_DATA
          SMime-type "signed-data".
 
Fields inherited from class javax.mail.internet.MimeMultipart
ds, parsed
 
Fields inherited from class javax.mail.Multipart
contentType, parent, parts
 
Constructor Summary
SignedContent(boolean implicit)
          Creates a new SignedContent object for signing some message.
SignedContent(boolean implicit, Canonicalizer canonicalizer)
          Creates a new SignedContent object for signing some message.
SignedContent(boolean implicit, java.lang.String smimeType)
          Creates a new SignedContent object for signing some message.
SignedContent(CryptoContent cryptoContent, boolean implicit)
          Creates a new SignedContent for the given encrypted content to be signed.
SignedContent(javax.activation.DataSource dataSource)
          Creates a SignedContent object for parsing a signed S/MIME content from the given DataSource.
SignedContent(javax.activation.DataSource dataSource, Canonicalizer canonicalizer)
          Creates a SignedContent object for parsing a signed S/MIME content from the given DataSource.
SignedContent(java.io.InputStream in)
          Creates a SignedContent object for parsing a signed S/MIME content from the given input stream.
SignedContent(java.io.InputStream in, Canonicalizer canonicalizer)
          Creates a SignedContent object for parsing a signed S/MIME content from the given input stream.
 
Method Summary
 void addBodyPart(javax.mail.BodyPart part)
          This method is not supported.
 void addBodyPart(javax.mail.BodyPart part, int index)
          This method is not supported.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate)
          Uses the given private key to sign the content.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm)
          Uses the given private key to sign the content with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, Attribute[] signedAttributes)
          Signs this content using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, CertificateIdentifier encryptionCertID, boolean includeEncryptionCertIDForMSOE)
          Uses the given private key to sign the content with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, X509Certificate encryptionCertificate, boolean includeEncryptionCertIDForMSOE)
          Uses the given private key to sign the content with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCertificate, X509Certificate encryptionCertificate, boolean includeEncryptionCertIDForMSOE)
          Uses the given private key to sign the content.
 void addSigner(SignerInfo signerInfo)
          Adds the given signer information to this signed content.
 void checkForSMimeParts(boolean checkForSMimeParts)
          Turns on/off control to use SMimeMultiparts and SMimeBodyParts insteadof MimeMultipatrs and MimeBodyParts when supplying the content for this signed message.
 void clearAllSigners()
          Clears all SignerInfos.
 X509Certificate getCertificate(CertificateIdentifier signerIdentifier)
          Tries to find the signer certificate specified by the given CertificateIdentidier.
 java.security.cert.Certificate[] getCertificates()
          Returns the certificates included in this S/MIME messages.
 java.lang.Object getContent()
          Returns the content as a Java object.
 java.io.InputStream getContentInputStream()
          Returns an InputStream with the unparsed content.
 X509CRL[] getCRLs()
          Returns the CRLs included in this S/MIME messages.
 javax.activation.DataHandler getDataHandler()
          Return a DataHandler holding the content.
 java.io.InputStream getInputStream()
          Returns an InputStream from which the content can be read.
 SecurityLabelHandler getSecurityLabelHandler()
          Returns the SecurityLabelHandler of this SignedContent, if installed.
 SignerInfo[] getSignerInfos()
          Returns all the signer infos included in the underlying SignedData object.
 java.lang.String getSMimeType()
          Returns the S/MIME type of this SignedContent.
 void notifyEOF()
          Decode the SignedData when multipart/signed message.
 void setBlockSize(int blockSize)
          Sets the block size for defining the length of each definite primitive encoded octet string component.
 void setCertificates(java.security.cert.Certificate[] certificates)
          Sets the certificates to be included in the S/MIME message.
 void setContent(javax.mail.Multipart multipart)
          Supplies the content to be signed as MIME Multipart.
 void setContent(java.lang.Object content, java.lang.String type)
          Sets the content to be encrypted.
 void setContentContentHeaders(javax.mail.Header[] headers)
          Set some headers for the entity to be signed.
 void setContentContentTransferEncoding(java.lang.String cte)
          Sets the content transfer encoding of the entity to be signed.
 void setCRLs(X509CRL[] crls)
          Sets the crls to be included in the S/MIME message.
 void setDataHandler(javax.activation.DataHandler dataHandler)
          Sets the content wrapped by a javax.activation.DataHandler.
 void setHeaders(javax.mail.Part part)
          Sets additional headers of the part (message) containing this SignedContent.
static void setLineBufferSize(int bufSize)
          Sets the size (default: 8192) of the line buffer to be used for parsing lines of an explicit signed message.
 void setSecurityLabelHandler(SecurityLabelHandler securityLabelHandler)
          Sets a handler to control access to the inner (signer) content if SignerInfos with ESSSecurityLabel or EquivalentLabels attributes are included.
 void setText(java.lang.String text)
          Sets the text content to be signed.
protected  void updateHeaders()
          Overrides updateHeaders to do nothing (since header update already is done when setting the content).
 X509Certificate verify()
          Verifies this S/MIME signed content and returns the certificate of the signer (i.e. the signer with the SignerInfo at index 0).
 X509Certificate verify(int signerInfoIndex)
          Verifies this S/MIME signed content for the signer at index signerInfoIndex.
 void verify(java.security.PublicKey publicKey)
          Uses the given PublicKey to verify the signature of the signer (i.e. the signer with the SignerInfo at index 0).
 void verify(java.security.PublicKey publicKey, int signerInfoIndex)
          Uses the given PublicKey to verify the signature of the signer at index signerInfoIndex.
 SignerInfo verify(X509Certificate signerCertificate)
          Uses the provided signer certificate for verifying the signature that has been created by the signer being owner of the certificate.
 void writeTo(java.io.OutputStream os)
          Writes this SignedContent to the given output stream.
 
Methods inherited from class javax.mail.internet.MimeMultipart
createInternetHeaders, createMimeBodyPart, createMimeBodyPart, getBodyPart, getBodyPart, getCount, parse, setSubType
 
Methods inherited from class javax.mail.Multipart
getContentType, getParent, removeBodyPart, removeBodyPart, setMultipartDataSource, setParent
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface iaik.smime.CryptoContent
getContentType
 

Field Detail

SIGNED_DATA

public static final java.lang.String SIGNED_DATA
SMime-type "signed-data".

See Also:
Constant Field Values

CERTS_ONLY

public static final java.lang.String CERTS_ONLY
SMime-type "certs-only".

See Also:
Constant Field Values
Constructor Detail

SignedContent

public SignedContent(boolean implicit)
Creates a new SignedContent object for signing some message.

It is possible to create implicitly (application/pkcs7-mime) and explicitly (multipart/signed) signed S/MIME messages. Implicitly signed messages can only be read with a mail client which supports S/MIME because the content is included in the S/MIME signature (DER encoded ASN.1).

Explicitly signed messages consist of a multipart/signed content where the first part contains the human readable content and the second part contains the signature.

When using this constructor for creating an implicit message the smime-type parameter will not be set.

After having created the SignedContent object specify content, certificates,... and signer information and finally add the SignedContent to a MimeMessage object to be sent:

 // create an explicit signed message (content-type "multipart/signed")
 boolean implicit = false;
 SignedContent sc = new SignedContent(implicit);
 // set the content to be signed
 sc.setContent(...);
 // set the sender certificates; may also contain the encryption cert of the sender
 sc.setCertificates(certificates);
 // set the private key of the signer, identified by the corresponding certificate
 sc.addSigner(privateKey, signerCertificate);
 ...
 // create a MimeMessage object for the current mail session
 MimeMessage msg = new MimeMessage(session);
 ...
 // set sender, recipient(s), subject, ...
 ...
 // set the signed content
 msg.setContent(sc, sc.getContentType());
 // send the message
 Transport.send(msg);
 

Parameters:
implicit - true if the message shall be included in the signature, false otherwise

SignedContent

public SignedContent(boolean implicit,
                     java.lang.String smimeType)
Creates a new SignedContent object for signing some message. It is possible to create implicitly (application/pkcs7-mime) and explicitly (multipart/signed) signed S/MIME messages. Implicitly signed messages can only be read with a mail client which supports S/MIME because the content is included in the S/MIME signature (DER encoded ASN.1).

Explicitly signed messages consist of a multipart/signed content where the first part contains the human readable content and the second part contains the signature.

When creating an implicit message the smime-type may be set to either SignedContent.SIGNED_DATA ("signed-data") or SignedContent.CERTS_ONLY ("certs-only"). Per default (smimeType = null) the smime-type parameter is not set.

After having created the SignedContent object specify content, certificates,... and signer information and finally add the SignedContent to a MimeMessage object to be sent:

 // create an implicit signed message (content-type "application/pkcs7-mime")
 boolean implicit = true;
 SignedContent sc = new SignedContent(implicit, SignedContent.SIGNED_DATA);
 // set the content to be signed
 sc.setContent(...);
 // set the sender certificates; may also contain the encryption cert of the sender
 sc.setCertificates(certificates);
 // set the private key of the signer, identified by the corresponding certificate
 sc.addSigner(privateKey, signerCertificate);
 ...
 // create a MimeMessage object for the current mail session
 MimeMessage msg = new MimeMessage(session);
 ...
 // set sender, recipient(s), subject, ...
 ...
 // set the signed content
 msg.setContent(sc, sc.getContentType());
 // send the message
 Transport.send(msg);
 

Parameters:
implicit - true if the message shall be included in the signature, false otherwise
smimeType - the smime-type (SignedContent.SIGNED_DATA or SignedContent.CERTS_ONLY)

SignedContent

public SignedContent(boolean implicit,
                     Canonicalizer canonicalizer)
Creates a new SignedContent object for signing some message.

It is possible to create implicitly (application/pkcs7-mime) and explicitly (multipart/signed) signed S/MIME messages. Implicitly signed messages can only be read with a mail client which supports S/MIME because the content is included in the S/MIME signature (DER encoded ASN.1).

Explicitly signed messages consist of a multipart/signed content where the first part contains the human readable content and the second part contains the signature.

When using this constructor for creating an implicit message the smime-type parameter will not be set.

After having created the SignedContent object specify content, certificates,... and signer information and finally add the SignedContent to a MimeMessage object to be sent.

Parameters:
implicit - true if the message shall be included in the signature, false otherwise
canonicalizer - the Canonicalizer to be used for content canonicalization in explcit mode (mulitpart/signed message)

SignedContent

public SignedContent(CryptoContent cryptoContent,
                     boolean implicit)
              throws javax.mail.MessagingException
Creates a new SignedContent for the given encrypted content to be signed.

This constructor may be used for creating an S/MIME message that is encrypted first and then signed, e.g.:

 EncryptedContent ec = ...;
 ec.setSMimeType();
 ...
 boolean implicit = true;
 SignedContent sc = new SignedContent(ec);
 ..
 MimeMessage mime = ...;
 mime.setContent(sc, sc.getContentType());
 sc.setHeaders(mime);
 ...
 

Parameters:
cryptoContent - the (signed or encrypted or compressed) content to be signed
implicit - whether to create an implcit (application/pkcs7-mime) or explicit signed message (multipart/signed)
Throws:
if - an error occurs when setting the content
javax.mail.MessagingException - if an error occurs while preparing the content

SignedContent

public SignedContent(javax.activation.DataSource dataSource)
              throws java.io.IOException
Creates a SignedContent object for parsing a signed S/MIME content from the given DataSource.

From the given data source the content type of the inherent message is parsed to determine if it represents an application/(x-)pkcs7-mime (implicit), or an multipart/sigend (explicit) message.

During a mail session an application usually will not call this constructor directly. Rather it will be called by a proper data content handler signed_content supplying the data source.

For more information about data handling using the javax.activation.DataSource for "MIME type based" data access, see the JavaBeans Activation Framework (JAF) sepecification.

Parameters:
dataSource - the DataSource
Throws:
java.io.IOException - if an error occurs when parsing the message, e.g. the content type is not application/(x-)pkcs7-mime or multipart/sigend, or the message content cannot be read

SignedContent

public SignedContent(javax.activation.DataSource dataSource,
                     Canonicalizer canonicalizer)
              throws java.io.IOException
Creates a SignedContent object for parsing a signed S/MIME content from the given DataSource.

From the given data source the content type of the inherent message is parsed to determine if it represents an application/(x-)pkcs7-mime (implicit), or an multipart/sigend (explicit) message.

During a mail session an application may not call this constructor directly. Rather it will be called by a proper data content handler signed_content supplying the data source.

For more information about data handling using the javax.activation.DataSource for "MIME type based" data access, see the JavaBeans Activation Framework (JAF) sepecification.

Parameters:
dataSource - the DataSource
canonicalizer - the Canonicalizer to be used for content canonicalization
Throws:
java.io.IOException - if an error occurs when parsing the message, e.g. the content type is not application/(x-)pkcs7-mime or multipart/sigend, or the message content cannot be read

SignedContent

public SignedContent(java.io.InputStream in)
              throws java.io.IOException
Creates a SignedContent object for parsing a signed S/MIME content from the given input stream.

From the given input stream the content type of the inherent message is parsed to determine if it represents an application/(x-)pkcs7-mime (implicit), or an multipart/sigend (explicit) message.

Parameters:
in - the input stream the stream from which to read the signed content
Throws:
java.io.IOException - if an error occurs when parsing the message, e.g. the content type is not application/(x-)pkcs7-mime or multipart/sigend, or the message content cannot be read

SignedContent

public SignedContent(java.io.InputStream in,
                     Canonicalizer canonicalizer)
              throws java.io.IOException
Creates a SignedContent object for parsing a signed S/MIME content from the given input stream.

From the given input stream the content type of the inherent message is parsed to determine if it represents an application/(x-)pkcs7-mime (implicit), or an multipart/sigend (explicit) message.

Parameters:
in - the input stream the stream from which to read the signed content
canonicalizer - the Canonicalizer to be used for content canonicalization
Throws:
java.io.IOException - if an error occurs when parsing the message, e.g. the content type is not application/(x-)pkcs7-mime or multipart/sigend, or the message content cannot be read
Method Detail

setLineBufferSize

public static void setLineBufferSize(int bufSize)
Sets the size (default: 8192) of the line buffer to be used for parsing lines of an explicit signed message.

Parameters:
bufSize - the (initial) size of the line buffer

notifyEOF

public void notifyEOF()
               throws java.io.IOException
Decode the SignedData when multipart/signed message. This method automatically is called when the data carrying message part has been read.
Attention: This method is only public because it implements the EOFListener interface. This method shall NOT be called by an application.

Specified by:
notifyEOF in interface EOFListener
Throws:
java.io.IOException - if an error occurs while parsing the SignedData from a stream

setDataHandler

public void setDataHandler(javax.activation.DataHandler dataHandler)
                    throws javax.mail.MessagingException
Sets the content wrapped by a javax.activation.DataHandler. The DataHandler wraps around the actual content, e.g.:
 DataHandler dataHandler = new DataHandler(...);
 SignedContent sc = ...;
 sc.setDataHandler(dataHandler);
 
For more information about DataHandler usage see the JavaBeans Activation Framework (JAF) sepecification.

Parameters:
dataHandler - the DataHandler with the content to be signed
Throws:
javax.mail.MessagingException - if an error occurs while preparing the content

setContent

public void setContent(java.lang.Object content,
                       java.lang.String type)
                throws javax.mail.MessagingException
Sets the content to be encrypted.

Parameters:
content - a Java object
type - MIME type of this object
Throws:
javax.mail.MessagingException - if an error occurs while preparing the content

updateHeaders

protected void updateHeaders()
                      throws javax.mail.MessagingException
Overrides updateHeaders to do nothing (since header update already is done when setting the content).

Overrides:
updateHeaders in class javax.mail.internet.MimeMultipart
Throws:
javax.mail.MessagingException

setText

public void setText(java.lang.String text)
             throws javax.mail.MessagingException
Sets the text content to be signed. The supplied text will be packed into a MIME entity with content type "text/plain".

Parameters:
text - the text content
Throws:
javax.mail.MessagingException - if an error occurs while preparing the content

setContent

public void setContent(javax.mail.Multipart multipart)
                throws javax.mail.MessagingException
Supplies the content to be signed as MIME Multipart.

Parameters:
multipart - the multipart content
Throws:
javax.mail.MessagingException - if an error occurs while preparing the content

addBodyPart

public void addBodyPart(javax.mail.BodyPart part)
                 throws javax.mail.MessagingException
This method is not supported. Does nothing.

Overrides:
addBodyPart in class javax.mail.Multipart
Parameters:
part - the body part to be added; not used
Throws:
javax.mail.MessagingException

addBodyPart

public void addBodyPart(javax.mail.BodyPart part,
                        int index)
                 throws javax.mail.MessagingException
This method is not supported. Does nothing.

Overrides:
addBodyPart in class javax.mail.Multipart
Parameters:
part - the body part to be added; not used
index - the index; not used
Throws:
javax.mail.MessagingException

setContentContentTransferEncoding

public void setContentContentTransferEncoding(java.lang.String cte)
Sets the content transfer encoding of the entity to be signed. This method allows to set the content transfer encoding for the inner entity when method setText or setDataHandler has been used for supplying the content. This method maybe called BEFORE setting the content (to avoid header update overhead during the saveChanges run).

Parameters:
cte - the content transfer encoding to be applied to the inner entity to be signed

setContentContentHeaders

public void setContentContentHeaders(javax.mail.Header[] headers)
Set some headers for the entity to be signed. This method allows to set some headers for the inner entity when method setText or setDataHandler has been used for supplying the content. This method maybe called BEFORE setting the content (to avoid header update overhead during the saveChanges run).

Parameters:
headers - the headers to be applied to the inner entity to be signed

verify

public X509Certificate verify()
                       throws CMSSignatureException
Verifies this S/MIME signed content and returns the certificate of the signer (i.e. the signer with the SignerInfo at index 0).

This method may be used for verifying the signature when only one signer is included.

To use this method the certificate of the signer must be included in the signature. Use verify(PublicKey) for verification when the signer certificate is not included in the signature.

Returns:
the certificate of the signer
Throws:
CMSSignatureException - if this message does not verify, the signer certificate is not included in the message or if this is a certs-only message
CertificateNotFoundException - if the certificate of the signer is not included in this SignedData object
InvalidContentHashException - if the signature verification process fails because the content hash does not match to value of the included MessageDigest attribute
InvalidSignatureValueException - if the signature verification process fails because the signature value is invalid

verify

public X509Certificate verify(int signerInfoIndex)
                       throws CMSSignatureException
Verifies this S/MIME signed content for the signer at index signerInfoIndex.

The signature is verified by using the specified signer public key, which is get from the signer certificate, derived from the certificates field.

To use this method the certificate of the signer must be included in the signature. Use verify(PublicKey, int) for verification when the signer certificate is not included in the signature.

Returns:
the certificate of the signer
Throws:
CMSSignatureException - if this message does not verify, the signer certificate is not included in the message or if this is a certs-only message; or a parsing error occurs when
CertificateNotFoundException - if the certificate of the signer is not included in this SignedData object
InvalidContentHashException - if the signature verification process fails because the content hash does not match to value of the included MessageDigest attribute
InvalidSignatureValueException - if the signature verification process fails because the signature value is invalid

verify

public void verify(java.security.PublicKey publicKey)
            throws CMSSignatureException
Uses the given PublicKey to verify the signature of the signer (i.e. the signer with the SignerInfo at index 0).

This method may be used for verifying the signature when only one signer is included and the certificate of the signer is not included.

Throws:
CMSSignatureException - if this message does not verify or if this is a certs-only message
InvalidContentHashException - if the signature verification process fails because the content hash does not match to value of the included MessageDigest attribute
InvalidSignatureValueException - if the signature verification process fails because the signature value is invalid

verify

public void verify(java.security.PublicKey publicKey,
                   int signerInfoIndex)
            throws CMSSignatureException
Uses the given PublicKey to verify the signature of the signer at index signerInfoIndex.

This method may be used for verifying the signature when the certificate of the signer in mind is not included.

Throws:
CMSSignatureException - if this message does not verify or if this is a certs-only message; or a parsing error occurs when
InvalidContentHashException - if the signature verification process fails because the content hash does not match to value of the included MessageDigest attribute
InvalidSignatureValueException - if the signature verification process fails because the signature value is invalid

verify

public SignerInfo verify(X509Certificate signerCertificate)
                  throws CMSSignatureException
Uses the provided signer certificate for verifying the signature that has been created by the signer being owner of the certificate.

This method may be used for verifying the signature of a signer in situations where there are no certificates sent with the SignedData object. Of course, it also may be used when the certificate is not empty. However, take in mind that you should not step through the entries of the certificates field for calling verify(cert) for any certificate presented there since there also may (shall) be included issuer certificates and certificate chains leading to some trusted root.

Parameters:
signerCertificate - the certificate of the signer whose signature should be verified
Returns:
the signerInfo belonging to the signer being owner of the given certificate
Throws:
CMSSignatureException - if the signature turns out to be incorrect or there is no signer with the given certificate
InvalidContentHashException - if the signature verification process fails because the content hash does not match to value of the included MessageDigest attribute
InvalidSignatureValueException - if the signature verification process fails because the signature value is invalid

getContent

public java.lang.Object getContent()
                            throws java.io.IOException,
                                   javax.mail.MessagingException,
                                   SecurityLabelException
Returns the content as a Java object. The type of the returned object depends on the content itself. For example, the object returned for "text/plain" content is usually a String object. For content-types that are unknown to the JAF data content handler system, an input stream is returned as the content.

Returns:
the content as Java object
Throws:
java.io.IOException - if an I/O error occurs when getting the content from the inherent data handler
javax.mail.MessagingException - if an error occurs when fetching the inherent data handler
SecurityLabelException - if a SecurityLabelHandler is installed and an ESSSecurityLabel attribute is included in the SignerInfos the SecurityLabelHandler may decide to restrict access to the content

getDataHandler

public javax.activation.DataHandler getDataHandler()
                                            throws javax.mail.MessagingException,
                                                   SecurityLabelException
Return a DataHandler holding the content.

Returns:
a DataHandler with the content
Throws:
javax.mail.MessagingException - if an error occurs when fetching the data handler
SecurityLabelException - if a SecurityLabelHandler is installed and an ESSSecurityLabel attribute is included in the SignerInfos the SecurityLabelHandler may decide to restrict access to the content

getInputStream

public java.io.InputStream getInputStream()
                                   throws java.io.IOException,
                                          javax.mail.MessagingException,
                                          SecurityLabelException
Returns an InputStream from which the content can be read. Any mail-specific transfer encodings will be decoded before the input stream is provided.

Returns:
an InputStream holding from which the content can be read
Throws:
java.io.IOException - if an I/O error occurs when getting the content from the inherent data handler
javax.mail.MessagingException - if an error occurs when fetching the inherent data handler
SecurityLabelException - if a SecurityLabelHandler is installed and an ESSSecurityLabel attribute is included in the SignerInfos the SecurityLabelHandler may decide to restrict access to the content

getContentInputStream

public java.io.InputStream getContentInputStream()
                                          throws java.io.IOException,
                                                 SecurityLabelException
Returns an InputStream with the unparsed content. No mail-specific transfer encodings will be decoded before the input stream is provided.

Attention!This method may be called only once since a stream only can be read once. However, if any of the content accessing methods like getContent or getDataHandler is called before calling getContentInputStream, getContentInputStream may be called repeadetly since in this case the content is internally kept by means of a DataHandler.

Returns:
an InputStream holding the unparsed content
Throws:
java.io.IOException - if an error occurs when reading the data
SecurityLabelException - if a SecurityLabelHandler is installed and an ESSSecurityLabel attribute is included in the SignerInfos the SecurityLabelHandler may decide to restrict access to the content

setCertificates

public void setCertificates(java.security.cert.Certificate[] certificates)
Sets the certificates to be included in the S/MIME message. The supplied certificate list is an array of X509Certificates representing the certifcate chain of the signer. It is intended that the certificate list is sufficient to contain chains from a recognized 'top level CA' to the signer.

Note: Setting the signer certificates is an optional task. If no signer certificates are included, the recipient explicitly has to supply the signer public key when verifying the message: verify(PublicKey). Otherwise - if the signer certificate chain is included in the S/MIME message - the verify() method obtains the signer public key from the inherent certificate and the recipient must not extra take care for explicitly supplying the public key.

Parameters:
certificates - an array of certificates

setCRLs

public void setCRLs(X509CRL[] crls)
Sets the crls to be included in the S/MIME message.

Parameters:
crls - an array of crls

setHeaders

public void setHeaders(javax.mail.Part part)
Sets additional headers of the part (message) containing this SignedContent. This method sets the Content-Disposition and Content-Transfer-Encoding headers:
 Content-Disposition: attachment;
     filename="smime.p7m" (or "smime.p7c", if certs-only message)
 Content-Transfer-Encoding: base64
 
If this SignedContent is used in implicit mode (application/pkcs7-mime), it is highly recommended to call this method to set the headers above for the part containing this SignedContent:
 MimeMessage msg = ...;
 SignedContent sc = ...;
 sc.setHeaders(msg);
 
If this method is not called, JavaMail may run method writeTo twice to determine the content transfer encoding to be used.

Specified by:
setHeaders in interface CryptoContent
Parameters:
part - the part for which the Content-Disposition and Content-Transfer-Encoding headers should be set

getCertificate

public X509Certificate getCertificate(CertificateIdentifier signerIdentifier)
                               throws CMSException
Tries to find the signer certificate specified by the given CertificateIdentidier.

This method searches the certificates field of this SignedData for a certificate identified by the given SignerIdentifier (either an IssuerAndSerialNumber or SubjectKeyIdentifier).

Parameters:
signerIdentifier - the signerIdentifier IssuerAndSerialNumber or SubjectKeyIdentifier) identifying the certificate to search for
Returns:
the X509Certificate belonging to the given SignerIdentifier, if detected; otherwise a CMSException is thrown
Throws:
CMSException - if the requested certificate cannot be found

getCertificates

public java.security.cert.Certificate[] getCertificates()
Returns the certificates included in this S/MIME messages.

Returns:
the certificates of this S/MIME message; the array may be empty if no certificates are included

getCRLs

public X509CRL[] getCRLs()
Returns the CRLs included in this S/MIME messages.

Returns:
the crls of this S/MIME message; the array may be empty if no crls are included

getSMimeType

public java.lang.String getSMimeType()
Returns the S/MIME type of this SignedContent. Possible values are certs-only and signed-data.

Specified by:
getSMimeType in interface CryptoContent
Returns:
the S/MIME type or null if not set

getSignerInfos

public SignerInfo[] getSignerInfos()
Returns all the signer infos included in the underlying SignedData object.

Returns:
an array containing all the SignerInfo objects

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate)
               throws java.security.NoSuchAlgorithmException
Uses the given private key to sign the content.

The digest and signature algorithm are automatically calculated from the private key algorithm. If you want to explicitly set digest/signature algorithm you may call some alternative addSigner method) The signer certificate is used to add information about the signer by issuer distinguished name and issuer-specific serial number. The recipient uses this information to find the signer certificate from the list of certificates or from anywhere else.

When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

  • Content-Type (PKCS#7 Data)
  • Signing-Time
  • S/MIME Capabilities specifying the following symmetric ciphers:
    • aes_aes256_CBC (AES in CBC mode with 256 bit key)
    • aes_aes128_CBC (AES in CBC mode with 128 bit key)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • des_CBC (DES in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SigningCertificate or SigningCertificateV2 if signerCertificate is not null
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after the hash calculation is completed.

Parameters:
privateKey - the private key to sign the content
signerCertificate - the certificate of the signer
Throws:
java.security.NoSuchAlgorithmException - if any of the required algorithms is not supported

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      X509Certificate encryptionCertificate,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Uses the given private key to sign the content.

Digest and signature algorithm are automatically calculated from the private key algorithm. If you want to explicitly set digest/signature algorithm you may call some alternative addSigner method). The signer certificate is used to add information about the signer by issuer distinguished name and issuer-specific serial number. The recipient uses this information to find the signer certificate from the list of certificates or from anywhere else.

When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

  • Content-Type (PKCS#7 Data)
  • Signing-Time
  • S/MIME Capabilities specifying the following symmetric ciphers:
    • aes_aes256_CBC (AES in CBC mode with 256 bit key)
    • aes_aes128_CBC (AES in CBC mode with 128 bit key)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • des_CBC (DES in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SMIMEEncryptionKeyPreference, if encryptionCertID is not null
  • a private MS attribute ("1.3.6.1.4.1.311.16.4") identifying the encryption cert if if encryptionCertID is not null and includeEncryptionCertIDForMSOE allowing MSOE to recognize the encryption certificate is different certs are used for signing and encryption
  • SigningCertificate or SigningCertificateV2 if signerCertificate is not null
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after the hash calculation is completed.

Inclusion of a special private Microsoft signed attribute (type: 1.3.6.1.4.1.311.16.4) for identifying the encryption certificate of the sender by IssuerAndSerialNumber might be useful to tell Outlook Express the encryption certificate to be used if separate certificates are used for signing and encryption. If you want to include this attribute, set includeEncryptionCertIDForMSOE to true and supply the IssuerAndSerialNumber of the encryption certificate ("encrypter").

Parameters:
privateKey - the private key to sign the content
signerCertificate - the certificate of the signer
encryptionCertificate - the encryption certificate of the sender (or null if signing and encryption cert are the same or no encryption certificate shall be indicated); if not null, an SMIMEEncryptionKeyPreference attribute of type IssuerAndSerialNumber will be included in the SignerInfo to indicate the encryption certificate of the signer
includeEncryptionCertIDForMSOE - if true, a private MS attribute will be included allowing MSOE to recognize the encryption cert of the signer if using different certs for signing/encryption
Throws:
java.security.NoSuchAlgorithmException - if any of the required algorithms is not supported

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm)
               throws java.security.NoSuchAlgorithmException
Uses the given private key to sign the content with the given signature algorithm.

The signer certificate is used to add information about the signer by issuer distinguished name and issuer-specific serial number. The recipient uses this information to find the signer certificate from the list of certificates or from anywhere else.

When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

  • Content-Type (PKCS#7 Data)
  • Signing-Time
  • S/MIME Capabilities specifying the following symmetric ciphers:
    • aes_aes256_CBC (AES in CBC mode with 256 bit key)
    • aes_aes128_CBC (AES in CBC mode with 128 bit key)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • des_CBC (DES in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SigningCertificate or SigningCertificateV2 if signerCertificate is not null
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after the hash calculation is completed.

Inclusion of a special private Microsoft signed attribute (type: 1.3.6.1.4.1.311.16.4) for identifying the encryption certificate of the sender by IssuerAndSerialNumber might be useful to tell Outlook Express the encryption certificate to be used if separate certificates are used for signing and encryption. If you want to include this attribute, set includeEncryptionCertIDForMSOE to true and supply the IssuerAndSerialNumber of the encryption certificate ("encrypter").

Parameters:
privateKey - the private key to sign the content
signerCertificate - the certificate of the signer
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the requested message digest algorithm is available

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      X509Certificate encryptionCertificate,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Uses the given private key to sign the content with the given signature algorithm.

The signer certificate is used to add information about the signer by issuer distinguished name and issuer-specific serial number. The recipient uses this information to find the signer certificate from the list of certificates or from anywhere else.

When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

  • Content-Type (PKCS#7 Data)
  • Signing-Time
  • S/MIME Capabilities specifying the following symmetric ciphers:
    • aes_aes256_CBC (AES in CBC mode with 256 bit key)
    • aes_aes128_CBC (AES in CBC mode with 128 bit key)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • des_CBC (DES in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SMIMEEncryptionKeyPreference, if encryptionCertID is not null
  • a private MS attribute ("1.3.6.1.4.1.311.16.4") identifying the encryption cert if if encryptionCertID is not null and includeEncryptionCertIDForMSOE allowing MSOE to recognize the encryption certificate is different certs are used for signing and encryption
  • SigningCertificate or SigningCertificateV2 if signerCertificate is not null
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after the hash calculation is completed.

Inclusion of a special private Microsoft signed attribute (type: 1.3.6.1.4.1.311.16.4) for identifying the encryption certificate of the sender by IssuerAndSerialNumber might be useful to tell Outlook Express the encryption certificate to be used if separate certificates are used for signing and encryption. If you want to include this attribute, set includeEncryptionCertIDForMSOE to true and supply the IssuerAndSerialNumber of the encryption certificate ("encrypter").

Parameters:
privateKey - the private key to sign the content
signerCertificate - the certificate of the signer
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
encryptionCertificate - the encryption certificate of the sender (or null if signing and encryption cert are the same or no encryption certificate shall be indicated); if not null, an SMIMEEncryptionKeyPreference attribute of type IssuerAndSerialNumber will be included in the SignerInfo to indicate the encryption certificate of the signer
includeEncryptionCertIDForMSOE - if true, a private MS attribute will be included allowing MSOE to recognize the encryption cert of the signer if using different certs for signing/encryption
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the requested message digest algorithm is available

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      CertificateIdentifier encryptionCertID,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Uses the given private key to sign the content with the given signature algorithm.

The signer certificate is used to add information about the signer by issuer distinguished name and issuer-specific serial number. The recipient uses this information to find the signer certificate from the list of certificates or from anywhere else.

When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

  • Content-Type (PKCS#7 Data)
  • Signing-Time
  • S/MIME Capabilities specifying the following symmetric ciphers:
    • aes_aes256_CBC (AES in CBC mode with 256 bit key)
    • aes_aes128_CBC (AES in CBC mode with 128 bit key)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • des_CBC (DES in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SMIMEEncryptionKeyPreference, if encryptionCertID is not null
  • a private MS attribute ("1.3.6.1.4.1.311.16.4") identifying the encryption cert if if encryptionCertID is not null and includeEncryptionCertIDForMSOE allowing MSOE to recognize the encryption certificate is different certs are used for signing and encryption
  • SigningCertificate or SigningCertificateV2 if signerCertificate is not null
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after the hash calculation is completed.

Inclusion of a special private Microsoft signed attribute (type: 1.3.6.1.4.1.311.16.4) for identifying the encryption certificate of the sender by IssuerAndSerialNumber might be useful to tell Outlook Express the encryption certificate to be used if separate certificates are used for signing and encryption. If you want to include this attribute, set includeEncryptionCertIDForMSOE to true and supply the IssuerAndSerialNumber of the encryption certificate ("encrypter").

Parameters:
privateKey - the private key to sign the content
signerCertificate - the certificate of the signer
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
encryptionCertID - an ID to identify the encryption certificate of the sender (or null if signing and encryption cert are the same or no encryption certificate shall be indicated); if not null, an SMIMEEncryptionKeyPreference attribute will be included in the SignerInfo to indicate the encryption certificate of the signer
includeEncryptionCertIDForMSOE - if true, a private MS attribute will be included allowing MSOE to recognize the encryption cert of the signer if using different certs for signing/encryption
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the requested message digest algorithm is available

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      Attribute[] signedAttributes)
               throws java.security.NoSuchAlgorithmException
Signs this content using the supplied signer private key with the given signature algorithm.

Please note that no signed attributes are created by this method (as done by the other addSigner methods). This method sets the supplied attributes for the SignerInfo to be created for the signer. If not included in the supplied attributes, the messageDigest is automatically calculated and set.

Parameters:
privateKey - the private key which shall be used for signing
signerCertificate - the certificate of the signer which must be used for verifying the signature
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the requested message digest algorithm is available

addSigner

public void addSigner(SignerInfo signerInfo)
               throws java.security.NoSuchAlgorithmException
Adds the given signer information to this signed content. Any attributes already have to be set in the given SignerInfo.

Parameters:
signerInfo - the signer information to be added
Throws:
java.security.NoSuchAlgorithmException - if there is no implementation for the message digest algorithm specified in the signerInfo

clearAllSigners

public void clearAllSigners()
Clears all SignerInfos.


setSecurityLabelHandler

public void setSecurityLabelHandler(SecurityLabelHandler securityLabelHandler)
Sets a handler to control access to the inner (signer) content if SignerInfos with ESSSecurityLabel or EquivalentLabels attributes are included.

Parameters:
securityLabelHandler - the SecurityLabelHandler to be set

getSecurityLabelHandler

public SecurityLabelHandler getSecurityLabelHandler()
Returns the SecurityLabelHandler of this SignedContent, if installed. A SecurityLabelHandler maybe installed to control access to the inner (signed) if SignerInfos with ESSSecurityLabel or EquivalentLabels attributes are included.

Returns:
the SecurityLabelHandler of this SignedContent, or null if no SecurityLabelHandler has been installed

setBlockSize

public void setBlockSize(int blockSize)
Sets the block size for defining the length of each definite primitive encoded octet string component. If the value of blockSize is smaller or equal to zero the whole encrypted data is encoded as definite primitive octet string.

Parameters:
blockSize - for defining the encoding scheme and setting the octet string component length, if positive

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException,
                    javax.mail.MessagingException
Writes this SignedContent to the given output stream. If this SignedContent is IMPLICIT a DER encoded byte array is written. If this SignedContent is EXPLICIT a MimeMultipart object is written.

Overrides:
writeTo in class javax.mail.internet.MimeMultipart
Throws:
java.io.IOException - if an error occurs while writing to the stream
javax.mail.MessagingException - if an error occurs when fetching the data to be written

checkForSMimeParts

public void checkForSMimeParts(boolean checkForSMimeParts)
Turns on/off control to use SMimeMultiparts and SMimeBodyParts insteadof MimeMultipatrs and MimeBodyParts when supplying the content for this signed message. Especially when creating a signed message of type multipart/signed ("clear-signed") care has to be taken to properly canonicalize -- in particular text -- messages to give the same unique representation on the sender side where the signature is created and on the recipient side where the signature is verified.
The content of a signed message may be composed of MimeMultiparts consiting theirselves of several MimeBodyParts. To ensure that these body parts are canonicalized, they have to be modelled as SMimeBodyPart objects rather than using plain MimeBodyParts. When building a multipart entity from several body parts, the SMimeBodyParts have to be inserted into a SMimeMultipart object instead of using a plain MimeMultipart.
To avoid verification problems due to usage of not canonicalized parts, IAIK-CMS by default checks if SMimeMultiparts and SMimeBodyParts are used when creating a signed message. An exception is thrown if only plain MimeBodyParts and MimeMultiparts are used. However, when signing an already canonicalized entity (e.g. the content of a message just parsed) this check for SMimeMultiparts/SMimeBodyParts may not be required. In this case it might give some processing overhead to convert any MimeMultipart and MimeBodyPart to the required SMimeMultipart respectively SMimeBodyPart. For that reason it is possible to turn off the SMimePart check for a particular SignedContent, SMimeMultipart and/or SMimeBodyPart object or generally disable the SMimeBodyPart check throughout the whole application environment. When choosing the latter option by calling
 SMimeParameters.setCheckForSMimeParts(false);
 
take care to continue to use SMimeBodyParts and SMimeMultiparts when signing a newly created yet not canoinicalized content.

Parameters:
checkForSMimeParts - whether to turn on/off SMimePart checking

This Javadoc may contain text parts from text parts from IETF Internet Standard specifications (see copyright note).

IAIK-CMS 5.1, (c) 2002 IAIK, (c) 2003 - 2010 SIC