Skip Headers

Oracle® Security Developer Tools Reference 10g Release 3 (10.1.3) B25372-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 6 Oracle S/MIME

This chapter provides an overview of Oracle S/MIME, describes key features and benefits, and explains how to set up and use Oracle S/MIME.

This chapter contains these topics:

- Oracle S/MIME Features and Benefits

- Setting Up Your Oracle S/MIME Environment

- Developing Applications with Oracle S/MIME

## 6.1 Oracle S/MIME Features and Benefits

Oracle S/MIME is a pure Java solution which provides the following features:

- Full support for X.509 Version 3 certificates with extensions, including certificate parsing and verification

- Support for X.509 certificate chains in PKCS #7 and PKCS #12 formats

- Private key encryption using PKCS #5, PKCS #8, and PKCS #12

- An integrated ASN.1 library for input and output of data in ASN.1 DER/BER format

## 6.2 Setting Up Your Oracle S/MIME Environment

The Oracle Security Developer Tools are installed with Oracle Application Server in `ORACLE_HOME`. This section explains how to set up your environment for Oracle S/MIME. It contains these topics:

- System Requirements for Oracle S/MIME

- Setting the CLASSPATH Environment Variable

### 6.2.1 System Requirements for Oracle S/MIME

In order to use Oracle S/MIME, your system must have the Java Development Kit (JDK) version 1.2.2 or higher. Oracle S/MIME also requires:

- An implementation of the JavaBeans Activation Framework (JAF). Sun's royalty-free implementation is available at:

  `http://www.javasoft.com/beans/glasgow/jaf.html`

- An implementation of the JavaMail API. Sun's royalty-free implementation is available at:

  `http://www.javasoft.com/products/javamail/index.html`

If you are using POP or IMAP, be sure to download Sun's POP3 (or IMAP) Provider, which is also available at the JavaMail page.

### 6.2.2 Setting the CLASSPATH Environment Variable

Your `CLASSPATH` environment variable must contain the full path and file names to all of the required jar and class files. Make sure the following items are included in your `CLASSPATH`:

- `osdt_core.jar` file

- `osdt_cert.jar` file

- `osdt_cms.jar` file

- `osdt_smime.jar` file

- Your JAF (Java Activation Framework), JavaMail, and POP3 provider installations.

Any application using the Oracle S/MIME API must have all the neccessary MIME types registered in its command map.

Some applications, specifically those reading S/MIME entries from a FileDataSource, will need to register the S/MIME file types.

#### 6.2.2.1 Setting the CLASSPATH on Windows

To set the `CLASSPATH` on Windows:

1. In your Windows Control Panel, select System.

2. In the System Properties dialog, select the Advanced tab.

3. Click Environment Variables.

4. In the User Variables section, click New to add a `CLASSPATH` environment variable for your user profile. If a `CLASSPATH` environment variable already exists, select it and click Edit.

5. Add the full path and file names for all the required jar and class files to the `CLASSPATH`.

   For example, your `CLASSPATH` might look like this:

       %CLASSPATH%;C:\ORACLE_HOME\jlib\osdt_core.jar;
       C:\ORACLE_HOME\jlib\osdt_cert.jar;
       C:\ORACLE_HOME\jlib\osdt_cms.jar;C:\ORACLE_HOME\jlib\osdt_smime.jar;
       C:\jaf-1.0.2\activation.jar;C:\javamail-1.3.1\mail.jar;

6. Click OK.

#### 6.2.2.2 Setting the CLASSPATH on UNIX

On UNIX, set your `CLASSPATH` environment variable to include the full path and file names of all of the required jar and class files. For example:

    setenv CLASSPATH $CLASSPATH:$ORACLE_HOME/jlib/osdt_core.jar:\
    $ORACLE_HOME/jlib/osdt_cert.jar:\
    $ORACLE_HOME/jlib/osdt_cms.jar:$ORACLE_HOME/jlib/osdt_smime.jar:\
    /usr/lib/jaf-1.0.2/activation.jar:/usr/lib/javamail-1.3.1/mail.jar

## 6.3 Developing Applications with Oracle S/MIME

This section describes selected interfaces and classes in the Oracle S/MIME API and illustrates their use. It includes these topics:

- Core Classes and Interfaces

- Supporting Classes and Interfaces

- Using the Oracle S/MIME Classes

Selected methods are described as appropriate.

### 6.3.1 Core Classes and Interfaces

This section describes core classes and interfaces in the Oracle S/MIME API, and explains how to create and parse S/MIME objects.

#### 6.3.1.1 The oracle.security.crypto.smime.SmimeObject Interface

The `oracle.security.crypto.smime.SmimeObject` interface represents an S/MIME object. Classes that implement this interface include:

- `SmimeSigned`

- `SmimeEnveloped`

- `SmimeMultipartSigned`

- `SmimeSignedReceipt`

- `SmimeCompressed`

Methods in this interface include:

    String generateContentType ()

Returns the content type string for this S/MIME object. For example:

    "application/pkcs7-mime; smime-type=signed-data"

    String generateContentType (boolean useStandardContentTypes)

If the argument is true, returns the same as `generateContentType()`; if false, returns old-style (Netscape) content type string. For example: "application/x-pkcs7-mime; smime-type=signed-data"

    void writeTo (java.io.OutputStream os, java.lang.String mimeType)

Outputs this object to the specified output stream.

#### 6.3.1.2 The oracle.security.crypto.smime.SmimeSignedObject Interface

The `oracle.security.crypto.smime.SmimeSignedObject` interface extends `SmimeObject`, and specifies methods common to all S/MIME signed objects, including `SmimeSigned` and `SmimeMultipartSigned`.

Methods in this interface include:

    Vector getCertificates ()

Returns the list of certificates included in this S/MIME object's signed content.

    Vector getCRLs ()

Returns the list of certificate revocation lists in the S/MIME object's signed content.

    javax.mail.internet.MimeBodyPart getEnclosedBodyPart ()

Returns the document which was signed.

    oracle.security.crypto.smime.ess.EquivalentLabels getEquivalentLabels (oracle.security.crypto.cert.X509 signerCert)

Returns the `EquivalentLabels` if present or `null`.

    oracle.security.crypto.smime.ess.ESSSecurityLabel getESSSecurityLabel (oracle.security.crypto.cert.X509 signerCert)

Returns the `ESSSecurityLabel` if present or `null`.

    oracle.security.crypto.smime.ess.MLExpansionHistory getMLExpansionHistory(
     oracle.security.crypto.cert.X509 signerCert)

Returns the `MLExpansionHistory` attribute if present or `null`.

    oracle.security.crypto.smime.ess.ReceiptRequest getReceiptRequest(
     oracle.security.crypto.cert.X509 signerCert)

Returns the `ReceiptRequest` attribute if present or `null`.

    oracle.security.crypto.smime.ess.SigningCertificate getSigningCertificate(
     oracle.security.crypto.cert.X509 signerCert)

Returns the `SigningCertificate`.

    void verify (oracle.security.crypto.cert.CertificateTrustPolicy trustPolicy)

Returns normally if the signed contents include at least one valid signature according to the specified trust policy, otherwise throws an `AuthenticationException`.

    void verifySignature (oracle.security.crypto.cert.X509 signerCert)

Returns normally if the signed contents contain a signature which can be validated by the given certificate, otherwise throws an `AuthenticationException`.

#### 6.3.1.3 The oracle.security.crypto.smime.SmimeSigned Class

The `oracle.security.crypto.smime.SmimeSigned` class represents an S/MIME signed message (.implements SmimeSignedObject). You may use this class to build a new message or parse an existing one.

Constructors and methods include:

    SmimeSigned (javax.mail.internet.MimeBodyPart content)

Creates a new `SmimeSigned` object, using the specified MIME body part for the contents to be signed.

    SmimeSigned ()

Creates a new empty `SmimeSigned` object, which is useful for building a "certificates-only" S/MIME message.

    SmimeSigned (InputStream is)

Creates a new `SmimeSigned` object by reading its encoding from the specified input stream.

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey
        oracle.security.crypto.cert.X509 signerCert,
        oracle.security.crypto.core.AlgorithmIdentifier digestAlgID)

Adds a signature to the message, using the specified private key, certificate, and message digest algorithm.

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey,
     oracle.security.crypto.cert.X509 signerCert,
     oracle.security.crypto.core.AlgorithmIdentifier digestAlgID,
          java.util.Date timeStamp)

Adds a signature to the message, including a time stamp.

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey,
        oracle.security.crypto.cert.X509 signerCert,
        oracle.security.crypto.core.AlgorithmIdentifier digestAlgID,
        SmimeCapabilities smimeCaps)

Adds a signature to the message, including S/MIME capabilities.

    javax.mail.internet.MimeBodyPart getEnclosedBodyPart ()

Returns the MIME body part that was signed.

To build a new message, use any of these three constructors:

    // Create a new S/MIME Signed Message
    SmimeSigned sig = new SmimeSigned();

    //         -OR-
    // Create a new S/MIME Signed Message with a specified MIME body part
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    SmimeSigned sig1 = new SmimeSigned(bp);

    //         -OR-
    // Create a new S/MIME Signed Message with a specified MIME body part
    // and a flag switching comression on or off
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    boolean useCompression = true;
    SmimeSigned sig2 = new SmimeSigned(bp, useCompression);

To parse a message, use the constructor that takes a `java.io.InputStream`:

    InputStream is = Input stream containing message to be parsed
    SmimeSigned sig = new SmimeSigned(is);

#### 6.3.1.4 The oracle.security.crypto.smime.SmimeEnveloped Class

The `oracle.security.crypto.smime.SmimeEnveloped` class represents an S/MIME enveloped message (implements SmimeObject), and may be used to build a new message or parse an existing one.

Constructors and methods include:

    SmimeEnveloped (javax.mail.internet.MimeBodyPart content,
        oracle.security.crypto.core.AlgorithmIdentifier contentEncryptionAlgID)

Creates a new `SmimeEnveloped` object from the specified MIME body part, using the specified content encryption algorithm.

    SmimeEnveloped (InputStream is)

Creates a new `SmimeEnveloped` object by reading its encoding from the specified input stream.

    void addRecipient (oracle.security.crypto.cert.X509 cert)

Encrypts the message for the recipient using the given public key certificate.

    byte[] getEncryptedContent ()

Returns the contents without decrypting.

    javax.mail.internet.MimeBodyPart getEnclosedBodyPart (
     oracle.security.crypto.core.PrivateKey recipientKey,
     oracle.security.crypto.cert.X509 recipientCert)

Returns the MIME body part for the recipient specified by `recipientCert`, after decryption using the given recipient private key.

Use the following code to build a new message:

    // Create a new S/MIME Enveloped Message with a specified MIME body part and a specified content
    // encryption algorithm
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    AlgorithmIdentifier algId = AlgID.aes256_CBC;
    SmimeEnveloped env = new SmimeEnveloped(bp, algId);

To parse a message, use the constructor that takes a `java.io.InputStream`:

    InputStream is = Input stream containing message to be parsed
        SmimeEnveloped env = new SmimeEnveloped(is);

#### 6.3.1.5 The oracle.security.crypto.smime.SmimeMultipartSigned Class

The `oracle.security.crypto.smime.SmimeMultipartSigned` class represents an S/MIME multi-part signed message. A multipart signed message is intended for email clients that are not MIME-aware. This class can be used to build a new message or parse an existing one.

Constructors and methods include:

    SmimeMultipartSigned (javax.mail.internet.MimeBodyPart bodyPart,
        oracle.security.crypto.core.AlgorithmIdentifier digestAlgID)

Creates a new `SmimeMultipartSigned` message, with the specified MIME body part and message digest algorithm.

    void addBodyPart (javax.mail.BodyPart part)

Inherited from `javax.mail.Multipart`, adds the specified body part to this `SmimeMultipartSigned` object. (See the javax.mail API documentation for more details.)

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey,
        oracle.security.crypto.cert.X509 signerCert)

Adds a signature to the message, using the specified private key and certificate.

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey,
        oracle.security.crypto.cert.X509 signerCert, java.util.Date timeStamp)

Adds a signature to the message, using the specified private key and certificate plus a time stamp.

    void addSignature (oracle.security.crypto.core.PrivateKey signerKey,
        oracle.security.crypto.cert.X509 signerCert, java.util.Date timeStamp,
        SmimeCapabilities smimeCaps)

Adds a signature to the message, using the specified private key and certificate, plus S/MIME capabilities.

    javax.mail.internet.MimeBodyPart getEnclosedBodyPart ()

Returns the MIME body part that was signed.

Use the following code to build a new message:

    // Create a new S/MIME Multipart Signed Message with a specified
    // MIME body part and a specified digest algorithm
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    AlgorithmIdentifier algId = AlgID.sha1;
    SmimeMutlipartSigned sig = new SmimeMultipartSigned(bp, algId);

To parse a message, use the constructor that takes a `javax.activation.DataSource`:

    DataSource ds = Data source containing message to be parsed
    SmimeMultipartSigned sig = new SmimeMultipartSigned(ds);

#### 6.3.1.6 The oracle.security.crypto.smime.SmimeSignedReceipt Class

The `oracle.security.crypto.smime.SmimeSignedReceipt` class represents an S/MIME wrapped and signed receipt. You may use this class to build a new message or parse an existing one.

To build a new message, use any of these four constructors:

    // Create a new S/MIME wrapped and signed receipt with the specified receipt,
    // the specified digest of the message's signed attributes
    // and the addresses of the receipt recipients
    ESSReceipt receipt = ESS receipt to include in message
    byte [] msgSigDigest = Digest of signed attributes to be included in message
    Address [] addresses = Addresses of receipt recipients
    SmimeSignedReceipt sig = new SmimeSigned(receipt, msgSigDigest, addresses);

     //         -OR-
    // Create a new S/MIME wrapped and signed receipt
    // with a specified S/MIME Signed Message containing the receipt
    SmimeSignedObject sso = S/MIME signed message containing receipt
    SmimeSignedReceipt sig1 = new SmimeSignedReceipt(sso);

    //         -OR-
    // Create a new S/MIME wrapped and signed receipt with a
    // specified S/MIME Signed Message containing the receipt,
    // the signer's certificate and the addresses of the receipt recipients
    SmimeSignedObject sso1 = S/MIME signed message containing receipt
    X509 signerCert = The message signer's certificate
    Address [] addresses1 = Addresses of receipt recipients
    SmimeSignedReceipt sig2 = new SmimeSignedReceipt(sso1, signerCert, addresses1);

    //         -OR-

    // Create a new S/MIME wrapped and signed receipt with a
    // specified S/MIME Signed Message containing the receipt,
    // the signer's certificate, the addresses of the receipt recipients and
    // a specified MLExpansionHistory attribute.
    SmimeSignedObject sso1 = S/MIME signed message containing receipt
    X509 signerCert = The message signer's certificate
    Address [] addresses1 = Addresses of receipt recipients
    MLExpansionHistory mlExpansionHistory = The MLExpansionHistory attribute
    SmimeSignedReceipt sig2 =
        new SmimeSignedReceipt(sso1, signerCert, addresses1, mlExpansionHistory);

To parse a message, use the constructor that takes a `java.io.InputStream`:

    InputStream is = Input stream containing message to be parsed
    SmimeSignedReceipt sig = new SmimeSignedReceipt(is);

#### 6.3.1.7 The oracle.security.crypto.smime.SmimeCompressed Class

The `oracle.security.crypto.smime.SmimeCompressed` class represents an S/MIME compressed message as defined in RFC 3274. You can use this class to build a new message or parse an existing one.

Note: A link to RFC 3274 is available in Appendix A, "References".

Use the following code to build a new message:

    // Create a new S/MIME Compressed Message with a specified MIME body part
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    SmimeCompressed comp = new SmimeCompressed(bp);

    //           -OR-
    // Create a new S/MIME Compressed Message with a specified MIME body part
    // and a specified compression algorithm
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Hello from SendSignedMsg!");
    AlgorithmIdentifier algId = Smime.id_alg_zlibCompress;
    SmimeCompressed comp = new SmimeCompressed(bp, algId);

To parse a message, use the constructor that takes a `java.io.InputStream`:

    InputStream is = Input stream containing message to be parsed
    SmimeCompressed comp1 = new SmimeCompressed(is);

### 6.3.2 Supporting Classes and Interfaces

This section describes Oracle S/MIME supporting classes and interfaces.

#### 6.3.2.1 The oracle.security.crypto.smime.Smime Interface

The `oracle.security.crypto.smime.Smime` interface defines constants such as algorithm identifiers, content type identifiers, and attribute identifiers.

#### 6.3.2.2 The oracle.security.crypto.smime.SmimeUtils Class

The `oracle.security.crypto.smime.SmimeUtils` class contains static utility methods.

Methods of this class include:

    public static FileDataSource createFileDataSource (File file,
        String contentTypeHeader)
    public static FileDataSource createFileDataSource (String name,
        String contentTypeHeader)

For transparent handling of multipart or multipart/signed S/MIME types, use these methods instead of directly instantiating a `javax.activation.FileDataSource`.

Note: The default `javax.activation.FileDataSource` included with JAF 1.0.1 does not handle multipart MIME boundaries when used with Javamail 1.1.x.

#### 6.3.2.3 The oracle.security.crypto.smime.MailTrustPolicy Class

The `oracle.security.crypto.smime.MailTrustPolicy` class implements a certificate trust policy (`oracle.security.crypto.cert.CertificateTrustPolicy`) used to verify signatures on signed S/MIME objects.

#### 6.3.2.4 The oracle.security.crypto.smime.SmimeCapabilities Class

The `oracle.security.crypto.smime.SmimeCapabilities` class encapsulates a set of capabilities for an S/MIME object including, for example, the supported encryption algorithms.

A useful method of this class is:

    void addCapability(oracle.security.crypto.asn1.ASN1ObjectID capabilityID)

which adds the capability with the specified object ID to this set of S/MIME capabilities.

#### 6.3.2.5 The oracle.security.crypto.smime.SmimeDataContentHandler Class

The `oracle.security.crypto.smime.SmimeDataContentHandler` class provides the DataContentHandler for S/MIME content types. It implements `javax.activation.DataContentHandler`.

#### 6.3.2.6 The oracle.security.crypto.smime.ess Package

The `oracle.security.crypto.smime.ess` package contains the following classes:

Table 6-1 Classes in the oracle.security.crypto.smime.ess Package

Class | Description
--- | ---
ContentHints | Content hints
ContentReference | Content reference
EquivalentLabels | ESS EquivalentLabels
ESSCertID | Represents the ESSCertID of a certificate which is used in the Signing Certificate Attribute
ESSSecurityLabel | An ESS security label
GeneralNames | The GeneralNames type, which is a SEQUENCE of the GeneralName type defined in RFC 2459 (a link to RFC 2459 is available in Appendix A, "References")
MLData | Represents the MLData element which is used in the MLExpansionHistory attribute
MLExpansionHistory | Mailing list expansion history
ReceiptRequest | An ESS Receipt Request
ReceiptRequest.AllOrFirstTier | A 'AllOrFirstTier' is a part of the 'ReceiptsFrom' field of a ReceiptRequest
SigningCertificate | An ESS Signing Certificate

### 6.3.3 Using the Oracle S/MIME Classes

This section describes how to use the Oracle S/MIME SDK to work with multi-part signed messages, create and open digital envelopes, and implement Enhanced Security Services (ESS). It covers these topics:

- Using the Abstract Class SmimeObject

- Signing Messages

- Creating "Multipart/Signed" Entities

- Creating Digital Envelopes

- Creating "Certificates-Only" Messages

- Reading Messages

- Authenticating Signed Messages

- Opening Digital Envelopes (Encrypted Messages)

- Adding Enhanced Security Services (ESS)

#### 6.3.3.1 Using the Abstract Class SmimeObject

`SmimeObject` is an abstract class representing a fundamental S/MIME message content entity. Subclasses of `SmimeObject` include `SmimeSigned`, `SmimeEnveloped`, and `SmimeMultipartSigned`.

One of the characteristics of `SmimeObject` implementations is that they "know their own MIME type" -- that is, they implement the `generateContentType` method. Thus, to place such an object inside a MIME message or body part, follow the same outline that was used in the `SmimeSigned` example:

1. Create the object.

2. Invoke `generateContentType` on the object to obtain a MIME type.

3. Pass the object, together with the generated content type, to the `setContent` method of a `MimeMessage` or `MimeBodyPart` object.

The `SmimeObject` class provides another version of the `generateContentType` method, which takes a boolean parameter. When given true as a parameter, `generateContentType` behaves exactly as in the case of no argument. When given false as a parameter, `generateContentType` returns the older MIME types required by certain mail clients, including Netscape Communicator 4.0.4. Specifically:

- "application/pkcs7-mime" becomes "application/x-pkcs7-mime"

- "application/pkcs7-signature" becomes "application/x-pkcs7-signature"

#### 6.3.3.2 Signing Messages

Create a signed message, or signed MIME body part, using these steps:

1. Prepare an instance of MimeBodyPart which contains the content you wish to sign. This body part may have any content-type desired. In the following example we create a "text/plain" body part:

       MimeBodyPart doc = new MimeBodyPart();
       doc.setText("Example signed message.");

2. Create an instance of `SmimeSigned` using the constructor which takes the MimeBodyPart created earlier as argument.

       SmimeSigned sig = new SmimeSigned (doc);

3. Add all desired signatures. For each signature, you need to specify a private key, a certificate for the matching public key, and a message digest algorithm. For example:

       sig.addSignature (signatureKey, signatureCert, AlgID.sha1);

   In this example we specified the SHA-1 message digest algorithm. Alternatively, we could have specified the MD5 algorithm by passing `AlgID.md5` as the argument.

4. Place your `SmimeSignedObject` into a `MimeMessage` or `MimeBodyPart`, as appropriate. For example:

       MimeMessage m = new MimeMessage();
       m.setContent (sig, sig.generateContentType());

   or

       MimeBodyPart bp = new MimeBodyPart();
       bp.setContent (sig, sig.generateContentType());

The `generateContentType` method used in these examples returns a string identifying the appropriate MIME type for the object, which in this case is:

    application/pkcs7-mime; smime-type=signed-data

With these simple steps, you can now transport the MIME message, place the body part containing S/MIME content into a MIME multipart object, or perform any other operation appropriate for these objects. See the JavaMail API for details.

#### 6.3.3.3 Creating "Multipart/Signed" Entities

The `SmimeMultipartSigned` class provides an alternative way to create signed messages. These messages use the "multipart/signed" mime type instead of "application/pkcs7-mime". The advantage is that the content of the resulting message is readable with non-MIME enabled mail clients, although such clients will not, of course, be able to verify the signature.

Creating a multi-part/signed message is slightly different from creating a signed message. For example, to send a multi-part/signed text message:

    // create the content text as a MIME body part
    MimeBodyPart bp = new MimeBodyPart();
    bp.setText("Example multipart/signed message.");
    // the constructor takes the signature algorithm
    SmimeMultipartSigned sig = new SmimeMultipartSigned(bp, AlgID.sha1);
    // sign the content
    sig.addSignature(signerKey, signerCert);
    // place the content in a MIME message
    MimeMessage msg = new MimeMessage();
    msg.setContent(sig, sig.generateContentType());

The reason for identifying the message digest in the `SmimeMultipartSigned` constructor is that, unlike the case of application/pkcs7-mime signed data objects, multipart/signed messages require that all signatures use the same message digest algorithm.

The `generateContentType` method returns the following string:

    multipart/signed; protocol="application/pkcs7-signature"

#### 6.3.3.4 Creating Digital Envelopes

An S/MIME digital envelope (encrypted message) is represented by the `SmimeEnveloped` class. This is a MIME entity which is formed by encrypting a MIME body part with some symmetric encryption algorithm (eg, Triple-Des or RC2) and a randomly generated session key, then encrypting the session key with the RSA public key for each intended message recipient.

In the following example, `doc` is an instance of `MimeBodyPart`, which is to be wrapped in an instance of `SmimeEnveloped`, and `recipientCert` is the recipient's certificate.

    SmimeEnveloped env = new SmimeEnveloped(doc, Smime.dES_EDE3_CBC);
    env.addRecipient (recipientCert);

Any number of envelope recipients may be added by making repeated calls to `addRecipient`.

#### 6.3.3.5 Creating "Certificates-Only" Messages

It is possible to create an S/MIME signed-data object that contains neither content nor signatures; rather, it contains just certificates, or CRLs, or both. Such entities can be used as a certificate transport mechanism. They have the special content type:

    application/pkcs7-mime; smime-type=certs-only

Here is an example:

    X509 cert1, cert2;
    SmimeSigned certBag = new SmimeSigned();
    certBag.addCertificate(cert1);
    certBag.addCertificate(cert2);

Now you can pass `certBag` to an appropriate `setContent` method. When `generateContentType` is invoked on `certBag`, it will automatically return a content type with the correct "certs-only" value for the `smime-type` parameter.

#### 6.3.3.6 Reading Messages

The basic JavaMail API technique for extracting Java objects from MIME entities is to invoke the `getContent()` method on an instance of `MimePart`, an interface which models MIME entities and is implemented by the `MimeMesage` and `MimeBodyPart` classes.

The `getContent` method consults the currently installed default command map - which is part of the JavaBeans Activities Framework - to find a data content handler for the given MIME type, which is responsible for converting the content of the MIME entity into a Java object of the appropriate class.

The `mailcap` file provided with your distribution can be used to install the `SmimeDataContentHandler` class, which serves as a data content handler for the following types:

Content Type | Returns Instance Of
--- | ---
application/pkcs7-mime | SmimeSigned or Smime Enveloped
application/pkcs7-signature | SmimeSigned
application/pkcs10 | oracle.security.crypto.cert.CertificateRequest
multipart/signed | SmimeMultipartSigned

#### 6.3.3.7 Authenticating Signed Messages

Once you obtain an instance of `SmimeSigned` or `SmimeMutlipartSigned` from `getContent()`, you will naturally want to verify the attached signatures. To explain the available options for signature verification, it is neccessary to discuss the structure of an S/MIME signed message.

The content of a signed S/MIME message is a CMS object of type `SignedData`. Such an object itself has a content - the document to which the signatures are applied - which is the text encoding of a MIME entity. It also contains from zero to any number of signatures, and, optionally, a set of certificates, CRLs, or both, which the receiving party may use to validate the signatures.

The `SmimeSigned` and `SmimeMultipartSigned` classes encapsulate all of this information. They provide two authentication methods: `verifyingSignature` and `verify`.

To verify a particular signature with a certificate already in possession, ignoring any certificate and CRLs attached by the signer, use `verifySignature`. For example:

    SmimeSignedObject sig =
        (SmimeSignedObject)msg.getContent(); // msg is a Message
    sig.verifySignature(cert, msg.getFrom()); // cert is an X509 object

If verification fails, the `verifySignature` method throws either an `UnknownSignerException` or an `AuthenticationException` ; otherwise, it returns normally.

Use `verify` to verify that the content contains at least one valid signature; that is, there exists a valid certificate chain, starting from a trusted root CA, and terminating in a certificate for the private key which generated the signature. This method makes use of the attached certificate and CRLs in order to follow certificate chains.

For example, given a trusted certificate authority (CA) certificate already in hand:

    TrustedCAPolicy trusts = new TrustedCAPolicy();
    // if true, need CRL for each cert in chain
    trusts.setRequireCRLs(false);
    // caCert is an X509 object with CA cert
    trusts.addTrustedCA(caCert);
    SmimeSignedObject sig = (SmimeSignedObject)msg.getContent();
    sig.verify(trusts, msg.getFrom());

Like `verifySignature`, `verify` throws an `AuthenticationException` if the signature cannot be verified; otherwise it returns normally. In either case you can recover the document that was signed, which is itself a MIME entity, by invoking `getEnclosedBodyPart()`:

    MimeBodyPart doc = sig.getEnclosedBodyPart();

#### 6.3.3.8 Opening Digital Envelopes (Encrypted Messages)

An S/MIME digital envelope consists of:

- A protected MIME body part, which has been encrypted with a symmetric key algorithm (for example, DES or RC2)

- A randomly generated content encryption key

- Information that allows one or more intended recipients to decrypt the content

For each recipient, this information consists of the content encryption key, itself encrypted with the recipient's public key.

To obtain the encrypted content from an `SmimeEnveloped` object, you need the recipient's private key and the corresponding certificate; the certificate is used as an index into the recipient information table contained in the envelope's data structure.

For example:

    SmimeEnveloped env = (SmimeEnveloped)msg.getContent();
    MimeBodyPart mbp = env.getEnclosedBodyPart(privKey, cert)
    // privKey is a PrivateKey object
    // cert is an X509 object

Passing the private key and the certificate to the `getEnclosedBodyPart` method returns the decrypted content as an instance of `MimeBodyPart`.

The `getContent` method can now be invoked on the `MimeBodyPart` object to retrieve the (now decrypted) content. This content may be a `String` (in the case of an encrypted text message), or any other object such as an `SmimeSigned`.

#### 6.3.3.9 Adding Enhanced Security Services (ESS)

You can add the ESS services `ReceiptRequests`, `SecurityLabels`, and `SigningCertificates` to an S/MIME signed message by adding them to the `signedAttributes` of a signature.

    // Create a Signed Message
    SmimeSigned sig = new SmimeSigned();
        AttributeSet signedAttributes = new AttributeSet();

Receipt Request`(oracle.security.crypto.smime.ess.ReceiptRequest)`

To request a signed receipt from the recipient of a message, add a `receiptRequest` attribute to the `signedAttributes` field while adding a signature:

    ReceiptRequest rr = new ReceiptRequest();
    .........
    signedAttributes.addAttribute(Smime.id_aa_receiptRequest, rr);

Security Label `(oracle.security.crypto.smime.ess.ESSSecurityLabel)`

To attach a security label to a message, add an `ESSSecurityLabel` attribute to the `signedAttributes` field while adding a signature:

    ESSSecurityLabel sl = new ESSSecurityLabel();
        .........
        signedAttributes.addAttribute(Smime.id_aa_securityLabel, sl);

Signing Certificate `(oracle.security.crypto.smime.ess.SigningCertificate)`

To attach a signing certificate to a message, add a `SigningCertificate` attribute to the `signedAttributes` field while adding a signature:

    SigningCertificate sc = new SigningCertificate();
        .........
        signedAttributes.addAttribute(Smime.id_aa_signingCertificate, sc);

Use the `signedAttributes` while adding a signature:

    sig.addSignature(signerKey, signerCert, digestAlgID, signedAttributes);

The ESS signed receipts are generated using the `SmimeSignedReceipt` class in the `oracle.security.crypto.smime` package, in a manner similar to using a `SmimeSigned` class, except that the content that is signed is an `oracle.security.crypto.cms.ESSReceipt` object.

#### 6.3.3.10 Processing Enhanced Security Services (ESS)

An S/MIME signed receipt must have correctly set content type parameters for the data content handlers to recognize it. If the content type parameters are missing, the signed receipt is treated as a signed message.

## 6.4 Oracle S/MIME Java API Reference

The Oracle S/MIME Java API Reference (Javadoc) is located at:

Oracle Security Developer Tools S/MIME Java API Reference