iaik.smime
Class SMimeSigned

java.lang.Object
  extended by iaik.cms.SignedDataStream
      extended by iaik.smime.SMimeSigned
All Implemented Interfaces:
EncodeListener, ContentStream, EOFListener, java.util.EventListener
Direct Known Subclasses:
JMailSMimeSigned

public class SMimeSigned
extends SignedDataStream

This class represents the "CMS SignedData object carrying" part of a S/MIME signed message.

This class extends the SignedDataStream class of the iaik.cms and may be used for creating and parsing CMS SignedData objects that are (to be) wrapped into a ContentInfo structure.

The steps for creating a SMimeSigned object and writing it to a stream may be summarized as follows (notice that the usage in general complies with that of the parent SignedDataStream, but is adopted to the specific requirements of the S/MIME protocol):

  1. Create a new SMimeSigned object thereby supplying the raw data to be signed as input stream and specifying the transmission mode to be used (either SMimeSigned.IMPLICIT for including the content as used for an application/pkcs7-mime message or SMimeSigned.EXPLICIT for transmitting the content outside the SignedData object):
         InputStream data_stream data_stream = ...;
         int mode = ...;
         SMimeSigned signed = new SMimeSigned(data_stream, mode);
         
  2. Set the signer certificates (may also contain the encryption certificate of the signer) by calling the setCertificates(Certificate[]) method:
         signed.setCertificates(certificates);
         
  3. Set signer information by calling the addSigner(PrivateKey, IssuerAndSerialNumber) method thereby supplying signer private key and IssuerAndSerialNumer of the signer certificate (note that when adding a Signer using this method, 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):
         PrivateKey signerPrivateKey = ...;
         X509Certificate signerCertificate = ...;
         signed.addSigner(signerPrivateKey, new IssuerAndSerialNumber(signerCertificate));
         
    The addSigner method creates an iaik.cms.SignerInfo object from the given information and sets the SignerInfo for the SMimeSigned SignedData object. Depending on which addSigner method is used, a set of signed standard attributes is added to the SignerInfo, as proposed by CMS and S/MIME. The following attributes are added, regardless of which addSigner method is used: The PKCS#9 message digest attribute automatically will be added later, during the data is written to a stream, and after hash calculation is completed.

    When calling an addSigner and specifying the certificate of the signer, an ESS SigningCertificate or SigningCertificateV2 attribute is added identifying the certificate of the signer.

    When calling an addSigner method where the encryption certificate of the signer is identified or specified an SMIMEEncryptionKeyPreference attribute and (optionally, if required) an a private MS attribute ("1.3.6.1.4.1.311.16.4") are added, both identifying the encryption certificate of the signer.

  4. If the mode chosen in step 1 when creating the SMimeSigned object has been SMimeSigned.EXPLICIT, now get and read the data from the data carrying input stream. Since in explicit mode the raw data is not included in the signature, the stream has to be read before actually performing the encoding. When reading the stream, the data is piped to digest stream for updating the hash computation.
         if (mode == SMimeSigned.EXPLICIT) {
           InputStream data_is = signed.getInputStream();
           byte[] buf = new byte[2048];
           int r;
           while ((r = data_is.read(buf)) > 0) {
             // do something useful
           }
         }
         
    When using the implicit mode, do not explicitly read data from the input stream at all! This will be done automatically during the last step when performing the encoding.

  5. Finally call the writeTo method for wrapping the SignedData object into a ContentInfo and writing it BER encoded to an output stream.
         signed.writeTo(output_stream);
         

On the recipient side it also has to be distinguished between IMPLICIT and EXPLICIT mode for parsing a received SMimeSigned message. When operating in IMPLICIT mode, the raw data is included in the received object, and so the parsing immediately may be performed when creating a SMimeSigned object from the BER encoded SMimeSigned message by calling the SMimeSigned(InputStream is) constructor. On the other side, when the raw data has been transmitted outside the signature (EXPLICIT mode), the SMimeSigned(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor has to be used for initializing the new SMimeSigned object with raw data and hash algorithms to be used for digest computation; and the decoding has to be performed explicitly by calling the decode method. The initialization is necessary for preparing the digest computation on the raw data. Later, during signature verification the digest value computaion is finished and the result is compared against the hash value resulting from decrypting the encrypted digest with the signer public key.
The individual steps necessary for parsing a received SMimeSigned message and verifying the signature may be summarized as follows:

  1. If the InputStream supplies the BER encoding of an implicit SMimeSigned object, use the SMimeSigned(InputStream is) constructor for creating a SMimeSigned object and implicitly performing the decoding:
         SMimeSigned signed = new SMimeSigned(encoded_stream);
         
    On the other hand, if the BER encoding represents an explicit SMimeSigned object, use the SMimeSigned(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor for initializing a new SMimeSigned object with raw data and digest algorithms for hash computation (e.g., one signer):
         AlgorithmID[] algID = { AlgorithmID.sha256 };
         SMimeSigned signed = new SMimeSigned(data_is, algIDs);
         
  2. Get the data carrying input stream and entirely read the data from the stream. This has to be performed for both implicit and explicit modes at exactly this state of the parsing procedure. In both cases the constructor has initialized the digest computation by wrapping a digest stream around the raw data stream for the specified hash algorithm, either implicitly read from the supplied SMimeSigned object, or explicitly supplied as an array of hash algorithm IDs. When now reading the stream, the data is piped through the digest stream for updating the hash computation:
         InputStream dataIs = signed.getInputStream();
         byte[] buf = new byte[2048];
         int r;
         while ((r = dataIs.read(buf)) > 0) {
           // do something useful
         }
         
  3. When dealing with an explicit message now explicitly perform the decoding by calling the decode method:
         signed.decode(encoded_stream);
         
  4. Now verify the signature and print the certificate of the signer:
          try {
             X509Certificate cert = signed.verify();
             System.out.println("Signature OK from: "+cert.getSubjectDN());
          } catch (SignatureException ex) {
              System.out.println("Signature ERROR!");
           }
         

See Also:
SignedDataStream, SignerInfo, SignedContent

Field Summary
 
Fields inherited from class iaik.cms.SignedDataStream
blockSize_, certSet_, contentType_, crls_, encapContentInfo_, EXPLICIT, IMPLICIT, inputStream_, mode_, securityProvider_, signerInfos_, thisObject_, version_
 
Constructor Summary
SMimeSigned(java.io.InputStream is)
          Reads a SMimeSigned message from an InputStream.
SMimeSigned(java.io.InputStream is, AlgorithmID[] hashAlgorithm)
          Creates a new SMimeSigned from an InputStream holding the signed data and an algorithm specifying the hash algorithm to use for digesting.
SMimeSigned(java.io.InputStream is, int mode)
          Creates a SMimeSigned object from an input stream which supplies the data to be signed.
SMimeSigned(java.io.InputStream is, ObjectID contentType, int mode)
          Creates a SMimeSigned object from an input stream which supplies the data to be signed.
 
Method Summary
 void addSigner(java.security.PrivateKey privateKey, IssuerAndSerialNumber signer)
          Signs this message using the supplied signer private key.
 void addSigner(java.security.PrivateKey privateKey, IssuerAndSerialNumber signer, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, IssuerAndSerialNumber signer, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, Attribute[] signedAttributes)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, IssuerAndSerialNumber signer, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, CertificateIdentifier encryptionCertId, boolean includeEncryptionCertIDForMSOE)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, IssuerAndSerialNumber signer, CertificateIdentifier encryptionCertId, boolean includeEncryptionCertIDForMSOE)
          Signs this message using the supplied signer private key.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCert, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, Attribute[] signedAttributes)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCert, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, CertificateIdentifier encryptionCertId, boolean includeEncryptionCertIDForMSOE)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCert, AlgorithmID digestAlgorithm, AlgorithmID signatureAlgorithm, X509Certificate encryptionCert, boolean includeEncryptionCertIDForMSOE)
          Signs this message using the supplied signer private key with the given signature algorithm.
 void addSigner(java.security.PrivateKey privateKey, X509Certificate signerCert, X509Certificate encryptionCert, boolean includeEncryptionCertIDForMSOE)
          Signs this message using the supplied signer private key.
 int getMode()
          Returns the mode of this message.
 ASN1Object toASN1Object(int blockSize)
          Returns the CMS SignedData object as an ASN1Object wrapped into a ContentInfo.
 java.lang.String toString()
          Returns a string representation of this message.
 X509Certificate verify()
          Verifies the signature and returns the certificate of the signer (i.e.
 void verify(java.security.PublicKey publicKey)
          Verifies the signature of the signer (i.e. the signer with the SignerInfo at index 0) with the provided public key.
 void writeTo(java.io.OutputStream os)
          Writes this SMimeSigned object to the supplied output stream.
 void writeTo(java.io.OutputStream os, int blockSize)
          Writes this SMimeSigned object to the supplied output stream.
 
Methods inherited from class iaik.cms.SignedDataStream
addCertificates, addCRLs, addDigestAlgorithm, addSDSEncodeListener, addSignerInfo, clearSignatures, decode, encodeCalled, getAttributeCertificates, getBlockSize, getCertificate, getCertificates, getCertificates, getCertificateSet, getContentType, getCRLs, getDigestAlgorithms, getEncapsulatedContentType, getInputStream, getMessageDigest, getRevocationInfoChoices, getSecurityProvider, getSignedDigest, getSignerInfo, getSignerInfo, getSignerInfoIndex, getSignerInfos, getVersion, getX509Certificates, notifyEOF, removeMessageDigest, removeSignerInfo, setBlockSize, setCertificates, setCertificateSet, setCRLs, setInputStream, setMessageDigest, setRevocationInfoChoices, setSDSEncodeListener, setSecurityProvider, setSignerInfos, toASN1Object, toString, verify, verify, verify
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

SMimeSigned

public SMimeSigned(java.io.InputStream is,
                   int mode)
Creates a SMimeSigned object from an input stream which supplies the data to be signed.

There are two possible modes:

  1. IMPLICIT: The message is included in der DER encoding. This means the message can only be read from an S/MIME aware mail client. If the signed message also is encrypted, IMPLICIT may be the better choice.
    The IMPLICIT mode corresponds to the application/pkcs7-mime content type.

  2. EXPLICIT: The message is not included in the DER encoding and must be added according to the MIME rules. The DER encoding only contains the signature of the message.
    The EXPLICIT mode corresponds to the multipart/signed content type.

Parameters:
is - a stream supplying the data to sign
mode - IMPLICIT if the message shall be included in the DER encoding, EXPLICIT otherwise

SMimeSigned

public SMimeSigned(java.io.InputStream is,
                   ObjectID contentType,
                   int mode)
Creates a SMimeSigned object from an input stream which supplies the data to be signed.

There are two possible modes:

  1. IMPLICIT: The message is included in der DER encoding. This means the message can only be read from an S/MIME aware mail client. If the signed message also is encrypted, IMPLICIT may be the better choice.
    The IMPLICIT mode corresponds to the application/pkcs7-mime content type.

  2. EXPLICIT: The message is not included in the DER encoding and must be added according to the MIME rules. The DER encoding only contains the signature of the message.
    The EXPLICIT mode corresponds to the multipart/signed content type.

Parameters:
is - a stream supplying the data to sign
contentType - the contentType for the inherent EncapsulatedContentInfo
mode - IMPLICIT if the message shall be included in the DER encoding, EXPLICIT otherwise

SMimeSigned

public SMimeSigned(java.io.InputStream is,
                   AlgorithmID[] hashAlgorithm)
            throws java.io.IOException
Creates a new SMimeSigned from an InputStream holding the signed data and an algorithm specifying the hash algorithm to use for digesting.

This constructor shall be used to process an already existing EXPLICIT SMimeSigned object. It will setup a DigestInputStream where the signed data is piped through. The new InputStream can be retrieved using the method getInputStream for reading the data and thereby piping it through a digest stream for hash calculation.

For subsequently processing the DER encoded SMimeSigned object, use method decode(InpuStream), e.g.:

 AlgorithmID[] algID = { AlgorithmID.sha256 };
 SMimeSigned signed = new SMimeSigned(data_is, algIDs);
 InputStream dataIs = signed.getInputStream();
 byte[] buf = new byte[2048];
 int r;
 while ((r = dataIs.read(buf)) > 0) {
   // do something useful
 }
 signed.decode(encoded_stream);
 

Parameters:
is - the InputStream holding the raw data supplied by other means, i.e. the first part of a multipart/signed message
hashAlgorithm - the hash algorithm(s) used for digesting the signed data; supplied as array of hash algorithms
Throws:
java.io.IOException - if an I/O error occurs or there is no implementation for the specified hash algorithm

SMimeSigned

public SMimeSigned(java.io.InputStream is)
            throws java.io.IOException
Reads a SMimeSigned message from an InputStream.

Do not use this constructor for supplying the content data to be signed. This constructor may be used by the recipient for parsing an already exisiting SMimeSigned object, supplied as DER encoding from an input stream, that may have been created by means of the writeTo method.

Use the SMimeSigned(InputStream data_is, int mode) constructor for supplying the content data to be signed when creating a SMimeSigned object.

This constructor only shall be used for decoding a SMimeSigned object with included raw data (implicit mode).
To initialize a SMimeSigned object for parsing an explicit message where the raw data is not included, use the SMimeSigned(InputStream is, AlgorithmID[] hashAlgorithms) constructor, and perform the decoding explicitly by calling the decode method.

Parameters:
is - the input stream where the DER encoded message shall be read from
Throws:
java.io.IOException - if an I/O error or parsing problem occurs
Method Detail

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      IssuerAndSerialNumber signer)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key. Digest and signature algorithm are be automatically calculated from the private key algorithm. If you want to explicitly set digest/signature algorithm you may call some alternative addSigner method).
The second parameter value, a IssuerAndSerialNumber object, sets the issuerAndSerialNumber field of the SignerInfo structure of the inherent SignedData object. This field is used for specifying the signer certificate by issuer distinguished name and issuer-specific serial number.

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

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 which shall be used for signing
signer - IssuerAndSerialNumber from the certificate which must be used for verifying the signature
Throws:
java.security.NoSuchAlgorithmException - if no implementation of the required algorithms is available.

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      IssuerAndSerialNumber signer,
                      CertificateIdentifier encryptionCertId,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key. Digest and signature algorithm are be automatically calculated from the private key algorithm. If you want to explicitly set digest/signature algorithm you may call some alternative addSigner method).
The second parameter value, a IssuerAndSerialNumber object, sets the issuerAndSerialNumber field of the SignerInfo structure of the inherent SignedData object. This field is used for specifying the signer certificate by issuer distinguished name and issuer-specific serial number.

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

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 ("encryptionCertId").

Parameters:
privateKey - the private key which shall be used for signing
signer - IssuerAndSerialNumber from the certificate which must be used for verifying the signature
encryptionCertId - the identifier of the encryption certificate of the sender by the SMIMEEncryptionKeyPreference attribute (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
includeEncryptionCertIDForMSOE - if true and an encryptionCertID of type IssuerAndSerialNumber is provided, 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 required algorithms is available.

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      X509Certificate signerCert,
                      X509Certificate encryptionCert,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key. Digest and signature algorithm are be 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 and the encryption certificate -- if not null -- of the signer will be identified by IssuerAndSerialNumber.

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

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 ("encryptionCertId").

Parameters:
privateKey - the private key which shall be used for signing
signerCert - the certificate of the signer which must be used for verifying the signature
encryptionCert - the encryption certificate of the sender to be identified by the SMIMEEncryptionKeyPreference attribute (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
includeEncryptionCertIDForMSOE - if true and an encryptionCertID of type IssuerAndSerialNumber is provided, 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 required algorithms is available.

addSigner

public void addSigner(java.security.PrivateKey privateKey,
                      IssuerAndSerialNumber signer,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream. When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

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 which shall be used for signing
signer - IssuerAndSerialNumber from the certificate 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(java.security.PrivateKey privateKey,
                      IssuerAndSerialNumber signer,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      CertificateIdentifier encryptionCertId,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream. When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

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 ("encryptionCertId").

Parameters:
privateKey - the private key which shall be used for signing
signer - IssuerAndSerialNumber from the certificate which must be used for verifying the signature
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
encryptionCertId - the identifier of the encryption certificate of the sender by the SMIMEEncryptionKeyPreference attribute (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
includeEncryptionCertIDForMSOE - if true and an encryptionCertID of type IssuerAndSerialNumber is provided, 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 signerCert,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      CertificateIdentifier encryptionCertId,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream. When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

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 ("encryptionCertId").

Parameters:
privateKey - the private key which shall be used for signing
signerCert - the certificate of the signer which must be used for verifying the signature
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
encryptionCertId - the identifier of the encryption certificate of the sender by the SMIMEEncryptionKeyPreference attribute (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
includeEncryptionCertIDForMSOE - if true and an encryptionCertID of type IssuerAndSerialNumber is provided, 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 signerCert,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      X509Certificate encryptionCert,
                      boolean includeEncryptionCertIDForMSOE)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream. When creating the SignerInfo object for the signer, the following attributes are set for the SignerInfo structure:

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 ("encryptionCertId").

Parameters:
privateKey - the private key which shall be used for signing
signerCert - the certificate of the signer which must be used for verifying the signature
digestAlgorithm - the digest algorithm
signatureAlgorithm - the signature algorithm
encryptionCert - the encryption certificate of the sender to be -- if not null -- identified by the SMIMEEncryptionKeyPreference attribute (or null if signing and encryption cert are the same or no encryption certificate shall be indicated)
includeEncryptionCertIDForMSOE - if true and an encryptionCertID of type IssuerAndSerialNumber is provided, 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,
                      IssuerAndSerialNumber signer,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      Attribute[] signedAttributes)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream.

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.

Parameters:
privateKey - the private key which shall be used for signing
signer - IssuerAndSerialNumber from the certificate 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(java.security.PrivateKey privateKey,
                      X509Certificate signerCert,
                      AlgorithmID digestAlgorithm,
                      AlgorithmID signatureAlgorithm,
                      Attribute[] signedAttributes)
               throws java.security.NoSuchAlgorithmException
Signs this message using the supplied signer private key with the given signature algorithm.

Calling this method also initializes the digest computation by wrapping a digest stream for the digest algorithm around the data carrying input stream.

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.

Parameters:
privateKey - the private key which shall be used for signing
signerCert - 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

verify

public X509Certificate verify()
                       throws CMSSignatureException
Verifies the signature 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.

Returns:
the certificate of the signer
Throws:
CMSSignatureException - if this message does not verify or the signer certificate is not included in the 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 void verify(java.security.PublicKey publicKey)
            throws CMSSignatureException
Verifies the signature of the signer (i.e. the signer with the SignerInfo at index 0) with the provided public key.

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

Parameters:
publicKey - the public key of the signer to verify the message
Throws:
CMSSignatureException - if this message does not verify
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

getMode

public int getMode()
Returns the mode of this message.

Overrides:
getMode in class SignedDataStream
Returns:
IMPLICIT or EXPLICIT

toASN1Object

public ASN1Object toASN1Object(int blockSize)
                        throws CMSException
Returns the CMS SignedData object as an ASN1Object wrapped into a ContentInfo. Automatically enforces block encoding with a block size of 2048 if a negative blockSize value is supplied.

Overrides:
toASN1Object in class SignedDataStream
Parameters:
blockSize - the block size for using block encoding
Returns:
this SMimeSigned object as an ASN1Object
Throws:
CMSException - if the ASN1Object could not be created

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException
Writes this SMimeSigned object to the supplied output stream. Automatically enforces block encoding with a block size of 2048.

Overrides:
writeTo in class SignedDataStream
Parameters:
os - the output stream to which this SMimeSigned shall be written
Throws:
java.io.IOException - if an error occurs while writing to the stream

writeTo

public void writeTo(java.io.OutputStream os,
                    int blockSize)
             throws java.io.IOException
Writes this SMimeSigned object to the supplied output stream. The blockSize parameter indicates the block size to be used for performimg block encoding.

Overrides:
writeTo in class SignedDataStream
Parameters:
os - the output stream to which this SMimeSigned shall be written
blockSize - the block size for performing block encoding
Throws:
java.io.IOException - if an error occurs while writing to the stream

toString

public java.lang.String toString()
Returns a string representation of this message.

Overrides:
toString in class SignedDataStream
Returns:
the string representation

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

IAIK-CMS 6.0, (c) 2002 IAIK, (c) 2003, 2023 SIC