iaik.smime.ess
Class ReceiptContent

java.lang.Object
  extended by iaik.smime.ess.ReceiptContent
All Implemented Interfaces:
CryptoContent

public class ReceiptContent
extends java.lang.Object
implements CryptoContent

This class can be used to create S/MIME messages for sending an signed receipt as response to receipt request.

When creating an signed receipt message you have to supply the original signer info requesting the receipt:

 SignerInfo originalSignerInfo = ...;
 ReceiptContent receiptContent = new ReceiptContent(originalSignerInfo);
 
Subsequently set the signer option as accustomed from SignedContent and send the message, e.g.:
 receiptContent.setCertificates(signerCertificates);
 receiptContent.setSigner(signerPrivateKey, signerCertificate, AlgorithmID.sha1, AlgorithmID.rsaEncryption,
                          encryptionCertOfSigner, true);
 MimeMessage msg = new MimeMessage(session);
 ...
 set sender, recipient(s), subject, ...
 ...
 msg.setContent(receiptContent, receiptContent.getContentType());
 receiptContent.setHeaders(msg); 
 Transport.send(msg);
 
Alternatively you may use the SignedReceipt utility for creating a SignedReceipt message in response to a receipt request message.

The receipt recipient (i.e. an entity to which it is requested to send a signed receipt) verifies the signed ReceiptContent message by calling a proper verify method and subsequently reads the included Receipt:

 ReceiptContent receiptContent = (ReceiptContent)msg.getContent();
 try {
    X509Certificate signer = receiptContent.verify();
    System.out.println("This message is signed from: "+signer.getSubjectDN());
 } catch (java.security.SignatureException ex) {
    ...
 }
 // get the content:
 Receipt receipt = (Receipt)receiptContent.getContent();
 ...
 
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 ReceiptContent to be sent per default the new S/MIME content types (application/pkcs7-mime) are used. For using the old types (application/x-pkcs7-mime) call the static useNewContentTypes method of the SMimeParameters class before creating a new ReceiptContent object, e.g.:

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

See Also:
Receipt, SignedReceipt

Constructor Summary
ReceiptContent(javax.activation.DataSource dataSource)
          Creates a ReceiptContent object from the given DataSource.
ReceiptContent(Receipt receipt)
          Creates a signed receipt message for an already existing Receipt.
ReceiptContent(SignerInfo originalSignerInfo)
          Creates a signed receipt message.
ReceiptContent(SignerInfo originalSignerInfo, SecurityProvider securityProvider)
          Creates a signed receipt message.
 
Method Summary
 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.lang.String getContentType()
          Returns the ContentType and any attached parameters of this ReceiptContent.
 X509CRL[] getCRLs()
          Returns the CRLs included in this S/MIME messages.
 Receipt getReceipt()
          Returns the Receipt included.
 SignerInfo[] getSignerInfos()
          Returns all the signer infos included in the underlying SignedData object.
 java.lang.String getSMimeType()
          Returns the S/MIME type parameter of this ReceiptContent.
 void setCertificates(java.security.cert.Certificate[] certificates)
          Sets the certificates to be included in the S/MIME message.
 void setCRLs(X509CRL[] crls)
          Sets the crls to be included in the S/MIME message.
 void setHeaders(javax.mail.Part part)
          Sets additional headers of the part (message) containing this ReceiptContent.
 void setSigner(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 setSigner(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 setSigner(SignerInfo signerInfo)
          Sets the signer of this ReceiptContent.
 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 ReceiptContent to the given output stream.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ReceiptContent

public ReceiptContent(SignerInfo originalSignerInfo)
               throws ESSException
Creates a signed receipt message. From the supplied SignerInfo information a Receipt and MsgSigDigest attribute is created as required for the signed receipt message.

Parameters:
originalSignerInfo - the original SignerInfo from the signer requesting the receipt.
Throws:
ESSException - if an error occurs when calculating the MsgSigDigest attribute from the original SignerInfo (e.g. no signed attributes are included in the SignerInfo; an error occurs while creating the required SET OF attributes, or the hash algorithm required for calculating the MsgSigDigest value is not available

ReceiptContent

public ReceiptContent(SignerInfo originalSignerInfo,
                      SecurityProvider securityProvider)
               throws ESSException
Creates a signed receipt message. From the supplied SignerInfo information a Receipt and MsgSigDigest attribute is created as required for the signed receipt message.

Parameters:
originalSignerInfo - the original SignerInfo from the signer requesting the receipt.
securityProvider - the securityProvider supplying the required cryptographic engines
Throws:
ESSException - if an error occurs when calculating the MsgSigDigest attribute from the original SignerInfo (e.g. no signed attributes are included in the SignerInfo; an error occurs while creating the required SET OF attributes, or the hash algorithm required for calculating the MsgSigDigest value is not available

ReceiptContent

public ReceiptContent(Receipt receipt)
Creates a signed receipt message for an already existing Receipt. An application using this constructor to create a ReceiptContent has to take care to calculate the required MsgSigDigest attribute itself. When later supplying information about the receipt signer be sure to use a method where you can supply the signed attributes (containing the MsgSigDigest attribute).

Parameters:
receipt - the Receipt calculated outside

ReceiptContent

public ReceiptContent(javax.activation.DataSource dataSource)
               throws java.io.IOException
Creates a ReceiptContent object from the given DataSource.

Parameters:
dataSource - the DataSource
Throws:
java.io.IOException - if an error occurs when parsing the message, e.g. an unknown MIME type is requested or the message content cannot be read
Method Detail

getContentType

public java.lang.String getContentType()
Returns the ContentType and any attached parameters of this ReceiptContent. This method shall be used when setting an ReceiptContent object as the content of a Message.
 Message msg = ...;
 ReceiptContent rc = new ReceiptContent();
 msg.setContent(rc, rc.getContentType());
 ...
 

Specified by:
getContentType in interface CryptoContent
Returns:
the content type of this ReceiptContent

verify

public X509Certificate verify()
                       throws java.security.SignatureException
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:
java.security.SignatureException - if this message does not verify, the signer certificate is not included in the message or if this is a certs-only message

verify

public X509Certificate verify(int signerInfoIndex)
                       throws java.security.SignatureException
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:
java.security.SignatureException - if this message does not verify, the signer certificate is not included in the message or if this is a certs-only message

verify

public void verify(java.security.PublicKey publicKey)
            throws java.security.SignatureException
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:
java.security.SignatureException - if this message does not verify or if this is a certs-only message

verify

public void verify(java.security.PublicKey publicKey,
                   int signerInfoIndex)
            throws java.security.SignatureException
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:
java.security.SignatureException - if this message does not verify or if this is a certs-only message

verify

public SignerInfo verify(X509Certificate signerCertificate)
                  throws java.security.SignatureException
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:
java.security.SignatureException - if the signature turns out to be incorrect or there is no signer with the given certificate

getContent

public java.lang.Object getContent()
Returns the content as a Java object.

Returns:
the Receipt included

getReceipt

public Receipt getReceipt()
Returns the Receipt included.

Returns:
the Receipt included

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 ReceiptContent. This method sets the Content-Disposition and Content-Transfer-Encoding headers:
 Content-Disposition: attachment";
     filename="smime.p7m"
 Content-Transfer-Encoding: base64
 
It is highly recommended to call this method to set the headers above for the part containing this ReceiptContent to avoid processing overhead :
 MimeMessage msg = ...;
 ReceiptContent rc = ...;
 rc.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

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 parameter of this ReceiptContent.

Specified by:
getSMimeType in interface CryptoContent
Returns:
the S/MIME type ("signed-receipt")

getSignerInfos

public SignerInfo[] getSignerInfos()
Returns all the signer infos included in the underlying SignedData object. Typically there will only be one SignerInfo in the array (since a SignedReceipt is only signed by one signer).

Returns:
an array containing all the SignerInfo objects

setSigner

public void setSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCertificate,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      X509Certificate encryptionCertificate,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException,
                      ESSException
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 (ESS receipt)
  • Signing-Time
  • S/MIME Capabilities specifying the follwing symmetric ciphers:
    • des_CBC (DES in CBC mode)
    • des_EDE3_CBC (TripleDes in CBC mode)
    • rc2_CBC (RC2 in CBC mode with 128, 64 or 40 bit key)
  • SMIMEEncryptionKeyPreference, if encryptionCertificate is not null
  • a private MS attribute ("1.3.6.1.4.1.311.16.4") identifying the encryption cert if if encryptionCertificate is not null and includeEncryptionCertIDForMSOE allowing MSOE to recognize the encryption certificate is different certs are used for signing and encryption
  • ESS MsgSigDigest representing the digest value on the original content
The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after SHA-1 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; default: SHA-1 (used, if null)
signatureAlgorithm - the signature algorithm; default: rsaEncryption (used, if null); Attention! use AlgorithmID.rsaEncryption for RSA signing!
encryptionCertificate - the encryption certificate of the sender (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
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
ESSException - if there occurs an error when adding the attributes

setSigner

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

Any attributes to be set already have to be included in the supplied signedAttributes (if no attributes are supplied, standard attributes will be added) except for the MsgSigDigest attribute which may be set by this method, if yet not included. The MsgSigDigest attribute only may be set by this method if this ReceiptContent has been created from the original SignerInfo (the one that belongs to the signer which requests the signed receipt). In this case the MsgSigDigest attribute has been calculated from the original SignerInfo and now can be added to the signed attributes. However, if this ReceiptContent has been created from an already existing Receipt we assume that the MsgSigDigest attribute also has been created outside and already is included in the signed attributes supplied to this method.

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; default: SHA-1 (used, if null)
signatureAlgorithm - the signature algorithm; default: rsaEncryption (used, if null); Attention! use AlgorithmID.rsaEncryption for RSA signing!
signedAttributes - the signedAttributes to be set for the SignerInfo of the receipt signer, if null or empty, standard attributes are added
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the requested message digest algorithm is available
ESSException - if an error occurs when setting the MsgSigDigestAttribute

setSigner

public void setSigner(SignerInfo signerInfo)
               throws java.security.NoSuchAlgorithmException,
                      ESSException
Sets the signer of this ReceiptContent.

Any attributes to be included into the SignerInfo already may be set (if no attributes are supplied, standard attributes will be added) except for the MsgSigDigest attribute which may be set by this method, if yet not included. The MsgSigDigest attribute only may be set by this method if this ReceiptContent has been created from the original SignerInfo (the one that belongs to the signer which requests the signed receipt). In this case the MsgSigDigest attribute has been calculated from the original SignerInfo and now can be added to the signed attributes. However, if this ReceiptContent has been created from an already existing Receipt we assume that the MsgSigDigest attribute also has been created outside and already is included in the signed attributes of the SignerInfo of the receipt signer supplied to this method.

Parameters:
signerInfo - the SignerInfo of the entity that signs the receipt
Throws:
java.security.NoSuchAlgorithmException - if there is no implementation for the message digest algorithm specified in the signerInfo
ESSException - if there occurs an error when adding the MsgSigDigest attribute

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException,
                    javax.mail.MessagingException
Writes this ReceiptContent to the given output stream.

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

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