iaik.pkcs.pkcs7
Class EncryptedContentInfoStream

java.lang.Object
  |
  +--iaik.pkcs.pkcs7.EncryptedContentInfoStream
Direct Known Subclasses:
EncryptedContentInfo

public class EncryptedContentInfoStream
extends Object

This class represents the stream-supporting implementataion of the PKCS#7 EncryptedContentInfo type.

The PKCS#7 Cryptographic Message Standard defines the EncryptedContentInfo type for specifying the content type, the content encryption algorithm and the encrypted content of an EnvelopedData, SignedAndEnvelopedData, or EncryptedData structure (Version 1.5):

 EncryptedContentInfo ::= SEQUENCE {
   contentType                 ContentType,
   contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
   encryptedContent            [0] IMPLICIT EncryptedContent OPTIONAL }
 
EncryptedContent ::= OCTET STRING

This class provides several constructors and methods for creating an EncryptedContentInfoStream, encrypting its content (thereby optionally creating a secret content-encryption key in accordance with the specified content-encryption algorithm), and "re-decrypting" the encrypted content again.

This class - as in common with all IAIK-JCE PKCS#7 implementations - provides mechanims for encoding the inherent encrypted content data as indefinite primitive octet string instead of using the default primitive definite encoding scheme:

 0x24 0x80
           0x04 <blocksize> <first encrypted content block>
           0x04 <blocksize> <second encrypted content block>
           0x04 <blocksize> <third encrypted content block>
                ...
 0x00 0x00
 
instead of:
 0x04 <length> <encrypted content>
 
The indefinte constrcuted encoding scheme may be preferable for properly handling large amounts of data, or/and when intending to be compatible to the encoding practice of some particular application (for instance some versions of Netscape Navigator).
For enabling an indefinte constructed encoding of the inherent encrypted content, the setBlockSize method has to be used for defining the length of each primitive definite encoded octet string component before actually performing the encoding by means of the writeTo method, e.g.:
 //create a EncryptedContentInfoStream for the data to be encrypted, supplied from an input stream:
 InputStream dataStream = ...;
 EncryptedContentInfoStream eci = new EncryptedContentInfoStream(ObjectID.pkcs7_data, dataStream);
 //generate secret key and set up the cipher for encryption:
 SecretKey key = eci.setupCipher(AlgorithmID.des_EDE3_CBC);
 //optionally set the block size for splitting the encoding:
 eci.setBlockSize(1024);
 //perform the content encryption and encode the EncryptedContentInfo to an output stream
 eci.writeTo(output_stream);
 
Note: in contrast to the equivalent non-stream supporting EncryptedContentInfo class, where the content encryption already is performed when calling a proper setupCipher method, this class performs the content encryption actually during the encoding by piping the data through a cipher stream when executing the writeTo method. The corresponding setupCipher method only initializes the cipher for the cipher stream pipe.

In the same way, when parsing an already existing EncryptedContentInfoStream object a proper setupCipher method has to be used for initializing the cipher stream pipe for decryption. The decryption actually is performed when reading the data previously obtained by means of the getInputstream method:

 //create an EncryptedContentInfoStream from the input stream supplying the encoding:
 EncryptedContentInfoStream eci = new EncryptedContentInfoStream(encoded_stream);
 //setup the cipher for decryption using the right secret key:
 eci.setupCipher(key);
 //get and read the data thereby actually performing the decryption
 InputStream data_is = eci.getInputStream();
 byte[] buf = new byte[1024];
 int r;
 while ((r = data_is.read(buf)) > 0) {
   // do something useful
 }
 
Attention! Special care has to be taken when using the default setup methods for initializing the content en/decryption as described above, particularly when the content encryption algorithm requires a specific key/parameter handling. In such cases, alternatively the setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec) respectively setupCipher(Key key, AlgorithmParameterSpec) methods shall be used to setup the cipher for content en/decryption. (see the method descriptions for more information).

Version:
File Revision 40
See Also:
EnvelopedDataStream, SignedAndEnvelopedDataStream, EncryptedDataStream

Constructor Summary
protected EncryptedContentInfoStream()
          Default constructor.
  EncryptedContentInfoStream(InputStream is)
          Creates a new EncryptedContentInfoStream where the DER encoded data is read from the given InputStream.
  EncryptedContentInfoStream(ObjectID contentType, AlgorithmID contentEncAlg)
          Creates an EncryptedContentInfoStream with given content type and content-encryption algorithm ID.
  EncryptedContentInfoStream(ObjectID contentType, InputStream is)
          Creates a new EncryptedContentInfoStream for the given content type where the content data to be encrypted is read from the provided InputStream.
 
Method Summary
protected  void decode(InputStream is)
          Reads and decodes the EncryptedContentInfoStream from a DerInputStream.
 int getBlockSize()
          Gets the block size defining the length of each definite primitive encoded octet string component.
 AlgorithmID getContentEncryptionAlgorithm()
          Returns the content-encryption algorithm (including any associated parameters) of this EncryptedContentInfoStream.
 ObjectID getContentType()
          Returns the type of the content encrypted by this EncryptedContentInfoStream.
 InputStream getInputStream()
          Returns an InputStream for reading the decrypted content.
 boolean hasContent()
          Returns true if there is a content.
 void setBlockSize(int blockSize)
          Sets the block size for encoding the encrypted content.
 SecretKey setupCipher(AlgorithmID contentEA)
          Setups the cipher and generates a secret key for encrypting the content.
 SecretKey setupCipher(AlgorithmID contentEA, int keyLength)
          Setups the cipher and generates a secret key for encrypting the content.
 void setupCipher(AlgorithmID contentEA, Key key, AlgorithmParameterSpec params)
          Setups the cipher for encrypting the content.
 void setupCipher(Key key)
          Uses the specified content-encryption key to setup the cipher for decrypting the content.
 void setupCipher(Key key, AlgorithmParameterSpec params)
          Uses the specified key and paramters to setup the cipher for decrypting the content.
 ASN1Object toASN1Object()
          Returns this EncryptedContentInfoStream as ASN1Object.
 String toString()
          Returns a string giving some information about this EncryptedContentInfoStream object.
 void writeTo(OutputStream os)
          Writes the BER encoding of this object to the given OutputStream.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

EncryptedContentInfoStream

protected EncryptedContentInfoStream()
Default constructor. The block size is set to 2048.

EncryptedContentInfoStream

public EncryptedContentInfoStream(ObjectID contentType,
                                  InputStream is)
Creates a new EncryptedContentInfoStream for the given content type where the content data to be encrypted is read from the provided InputStream.
Parameters:
contentType - the PKKCS#7 content type
is - the input stream holding the content data to encrypt

EncryptedContentInfoStream

public EncryptedContentInfoStream(ObjectID contentType,
                                  AlgorithmID contentEncAlg)
Creates an EncryptedContentInfoStream with given content type and content-encryption algorithm ID. The encrypted data must be supplied by other means.
Parameters:
contentType - the type of the encrypted content
contentEncAlg - the algorithm used to encrypt the content

EncryptedContentInfoStream

public EncryptedContentInfoStream(InputStream is)
                           throws IOException,
                                  PKCSParsingException
Creates a new EncryptedContentInfoStream where the DER encoded data is read from the given InputStream.

The given input stream supplies the DER encoding of an already exisiting EncryptedContentInfoStream object that may have been created by calling writeTo.

Use the EncryptedContentInfoStream(ObjectID contentType, InputStream is) constructor for supplying the content to be encrypted when creating an EncryptedContentInfoStream object.

Parameters:
is - the InputStream holding a DER encoded PKCS#7 EncryptedContentInfoStream object
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object
Method Detail

decode

protected void decode(InputStream is)
               throws IOException,
                      PKCSParsingException
Reads and decodes the EncryptedContentInfoStream from a DerInputStream. If the supplied InputStream actually is not an instance of DerInputStream, internally a DerInputStream is created before parsing the data.
Parameters:
is - the InputStream holding a DER encoded PKCS#7 EncryptedContentInfoStream object
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object

setupCipher

public void setupCipher(AlgorithmID contentEA,
                        Key key,
                        AlgorithmParameterSpec params)
                 throws NoSuchAlgorithmException,
                        InvalidKeyException,
                        InvalidAlgorithmParameterException
Setups the cipher for encrypting the content. If IV parameters are specified they are set for the given content encryption algorithm. This method creates a cipher for the specified content-encryption algorithm and initializes it with given key and parameters. The content encryption actually is performed during the encoding when writing this EncyrptedContentInfo to a stream by calling the writeTo method. So it is important to setup the cipher before writing to the stream!

Note: The supplied parameters are used for initializing the cipher. They may, for instance, constitute a initialization vector of type IvParameterSpec. In such cases, if the supplied contentEA algorithmID does not include parameters, an OCTET_STRING is created from the iv value and set as parameters for the contentEA algorithmID. However, if the contentEA algorithmID expects parameters of other ASN.1 representation than an OCTET_STRING constituting the IV, an application itself should take care for setting the parameters before supplying the algorithmID to this method. Imagine, for instance, RC2-CBC as used by S/MIME, where the parameters are encoded as SEQUENCE with two components having the OCTET_STRING iV as second component (see RFC 2311):

 RC2-CBC parameter ::=  SEQUENCE {
    rc2ParameterVersion  INTEGER,
    iv                   OCTET STRING (8)}
 
In such case an application may:
Parameters:
contentEA - the algorithm to use for encrypting the content
key - the key to use
params - the parameters to initialize the cipher
Throws:
NoSuchAlgorithmException - if there is no implementation for the specified algorithm
InvalidKeyException - if the key is inappropriate for the content-encryption algorithm
InvalidAlgorithmParameterException - if the provided parameters are not appropriate for the algorithm

setupCipher

public SecretKey setupCipher(AlgorithmID contentEA)
                      throws NoSuchAlgorithmException
Setups the cipher and generates a secret key for encrypting the content. Uses the default SecRandom to generate a new SecretKey for the specified algorithm. This method creates a cipher for the specified content-encryption algorithm and initializes it with the newly generated secret key. The content encryption actually is performed during the encoding when writing this EncyrptedContentInfo to a stream by calling the writeTo method. So it is important to setup the cipher before writing to the stream!

Attention! This method only shall be used for cipher setup if the secret key to be generated has a predefined length or default setting, since no key length parameter is offered. Furthermore, when using this method for cipher setup, it is expected that the algorithm parameters have to be encoded as OCTET_STRING. In cases where an alternaticve encoding is required (e.g. PBE, RC2), the setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec) method shall be used to setup the cipher for content encryption.

Parameters:
contentEA - the algorithm to use for encrypting the content
keyLength - the key length that may be set when using a content encryption algorithm that supports variable key lengths
Returns:
the new symmetric key for encrypting the content
Throws:
NoSuchAlgorithmException - if there is no implementation for the specified algorithm

setupCipher

public SecretKey setupCipher(AlgorithmID contentEA,
                             int keyLength)
                      throws NoSuchAlgorithmException
Setups the cipher and generates a secret key for encrypting the content. Uses the default SecRandom to generate a new SecretKey for the specified algorithm. If the specified content encryption algorithm supports variable key lengths, a particular key length may be set by means of the keyLength parameter. If no length is specified, the defined default key length will be used. If the algorithm only works with keys of fixed-size length, the keyLength parameter may be set to -1 or the setupCipher(AlgorithmID) method may be used.

This method creates a cipher for the specified content-encryption algorithm and initializes it with the newly generated secret key. The content encryption actually is performed during the encoding when writing this EncyrptedContentInfo to a stream by calling the writeTo method. So it is important to setup the cipher before writing to the stream!

Attention! This method only shall be used for cipher setup if the algorithm parameters represent an IV that has to be encoded as OCTET_STRING. In cases where an alternaticve encoding is required (e.g. PBE, RC2), the setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec) method shall be used to setup the cipher for content encryption.

Parameters:
contentEA - the algorithm to use for encrypting the content
keyLength - the key length that may be set when using a content encryption algorithm that supports variable key lengths
Returns:
the new symmetric key for encrypting the content
Throws:
NoSuchAlgorithmException - if there is no implementation for the specified algorithm

setupCipher

public void setupCipher(Key key,
                        AlgorithmParameterSpec params)
                 throws NoSuchAlgorithmException,
                        InvalidKeyException,
                        InvalidAlgorithmParameterException
Uses the specified key and paramters to setup the cipher for decrypting the content.

This method shall be used for initializing the cipher of an received EncryptedContentInfoStream object with key and parameters for decrypting the encrypted content, particularly when the parameters of the content encryption algorithmID do not constitute an OCTET_STRING that represents IV parameters. The following example parses PBE parameters from the algorithmID, and subsequently setups the cipher with key and derived parameters:

 //get the content encryption algorithm:
 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm();
 //get PBE parameters
 SEQUENCE seq = (SEQUENCE)contentEA.getParameter;
 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(0);
 byte[] salt = (byte[])oct.getValue();
 INTEGER iteration_count = (INTEGER)seq.getComponentAt(1);
 int it = ((BigInteger)iteration_count.getValue()).intValue();
 PBEParameterSpec params = new PBEParameterSpec(salt, it);
 //now setup the cipher
 eci.setupCipher(pbeKey, params);
 
The decryption actually is performed when subsequently getting and reading the data by means of the getInputStream method:
 //get and read the data thereby actually performing the decryption
 InputStream data_is = eci.getInputStream();
 byte[] buf = new byte[1024];
 int r;
 while ((r = data_is.read(buf)) > 0) {
   // do something useful
 }
 
It has to be noticed that the data should not be read before setting up the cipher!

Parameters:
key - the (secret) key to decrypt the content
params - the algorithm parameters needed to decrypt the content
Throws:
NoSuchAlgorithmException - if there is no implementation for the content-encryption-algorithm to be used
InvalidKeyException - if the key is inappropriate for the content-encryption algorithm
InvalidAlgorithmParameterException - if the provided parameters are not appropriate for the created cipher

setupCipher

public void setupCipher(Key key)
                 throws NoSuchAlgorithmException,
                        InvalidKeyException,
                        PKCSException
Uses the specified content-encryption key to setup the cipher for decrypting the content.

This method tries to get the IV from the content encryption algorithm.

This method shall be used for initializing the cipher of an received EncryptedContentInfoStream object with the right secret key for decrypting the encrypted content. The decryption actually is performed when subsequently getting and reading the data by means of the getInputStream method:

 //create an EncryptedContentInfoStream from the input stream supplying the encoding:
 EncryptedContentInfoStream eci = new EncryptedContentInfoStream(encoded_stream);
 //setup the cipher for decryption with the right secret key:
 eci.setupCipher(key);
 //get and read the data thereby actually performing the decryption
 InputStream data_is = eci.getInputStream();
 byte[] buf = new byte[1024];
 int r;
 while ((r = data_is.read(buf)) > 0) {
   // do something useful
 }
 
It has to be noticed that the data should not be read before setting up the cipher!

Attention! This method only can be used when the content encryption AlgorithmID contains IV parameters encoded as an OCTET_STRING. When the algorithmID contains parameters of other type (e.g. PBE parameters) they have to be decoded separatly, and the setupCipher(Key key, AlgorithmParameterSpec) method has to be used to setup the cipher for content decryption, e.g.:

 //get the content encryption algorithm:
 AlgorithmID contentEA = eci.getContentEncryptionAlgorithm();
 //get PBE parameters
 SEQUENCE seq = (SEQUENCE)contentEA.getParameter();
 OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(0);
 byte[] salt = (byte[])oct.getValue();
 INTEGER iteration_count = (INTEGER)seq.getComponentAt(1);
 int it = ((BigInteger)iteration_count.getValue()).intValue();
 PBEParameterSpec params = new PBEParameterSpec(salt, it);
 //now setup the cipher
 eci.setupCipher(pbeKey, params);
 

Parameters:
key - the (secret) key to decrypt the content
Throws:
NoSuchAlgorithmException - if there is no implementation for the content-encryption-algorithm to be used
InvalidKeyException - if the key is inappropriate for the content-encryption algorithm
PKCSException - if the algorithm parameter cannot be retrieved from the algorithm

setBlockSize

public void setBlockSize(int blockSize)
Sets the block size for encoding the encrypted content. If blockSize is positive, the encrypted content is encoded as indefinite constructed octet string being composed of a certain number of definite primitive encoded octet strings of blockSize length:
 0x24 0x80
           0x04 <blocksize> <first encrypted content block>
           0x04 <blocksize> <second encrypted content block>
           0x04 <blocksize> <third encrypted content block>
                ...
 0x00 0x00
 
If blockSize is not positive, whole the encrypted content is encoded as definite primitive octet string when calling the writeTo method:
  0x04 <length> <encrypted content>
 
Parameters:
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive

getBlockSize

public int getBlockSize()
Gets the block size defining the length of each definite primitive encoded octet string component. If the value of blockSize is smaller or equal to zero the whole data is encoded as definite primitive octet string. This method may be used for enforcing block encoding when wrapping the EncryptedData into a ContentInfo.
Returns:
blockSize defining the encoding scheme and setting the octet string component length, if positive
See Also:
OCTET_STRING

toASN1Object

public ASN1Object toASN1Object()
                        throws PKCSException
Returns this EncryptedContentInfoStream as ASN1Object.
Returns:
this EncryptedContentInfoStream as ASN1Object.

writeTo

public void writeTo(OutputStream os)
             throws IOException,
                    PKCSException
Writes the BER encoding of this object to the given OutputStream.

When encoding the content data to the given stream it is piped through a cipher stream thereby performing the content encryption.

If the setBlockSize method has been utilized for defining a positive blockSize value, the encrypted content is encoded as indefinite constructed octet string being composed of a certain number of definite primitive encoded octet strings of blockSize length:

 0x24 0x80
           0x04 <blocksize> <first encrypted content block>
           0x04 <blocksize> <second encrypted content block>
           0x04 <blocksize> <third encrypted content block>
                ...
 0x00 0x00
 
Otherwise, whole the encrypted content is encoded as definite primitive octet string:
  0x04 <length> <encrypted content>
 
Parameters:
os - the OutputStream to which the encoding shall be written to
Throws:
IOException - if an I/O error occurs during writing to the OutputStream
PKCSException - if an error occurs while encoding the object

getContentType

public ObjectID getContentType()
Returns the type of the content encrypted by this EncryptedContentInfoStream.
Returns:
the content type

getContentEncryptionAlgorithm

public AlgorithmID getContentEncryptionAlgorithm()
Returns the content-encryption algorithm (including any associated parameters) of this EncryptedContentInfoStream.
Returns:
the content-encryption AlgorithmID

getInputStream

public InputStream getInputStream()
Returns an InputStream for reading the decrypted content. Attention! The stream only may be read once.

When having created a new EncryptedContentInfoStream object to be encoded to a stream, this method should not be utilized at all, since the stream automatically will be read during performing the encoding (which is done when calling the writeTo method).
When having decoded and parsed a received EncryptedContentInfoStream object coming from some stream, this method may be used for obtaining the raw (decrypted) data after having done the cipher setup.

Returns:
an InputStream for reading the content data

hasContent

public boolean hasContent()
Returns true if there is a content.
Returns:
true if there is a content

toString

public String toString()
Returns a string giving some information about this EncryptedContentInfoStream object.
Overrides:
toString in class Object
Returns:
the string representation

This Javadoc may contain text parts from Internet Standard specifications (RFC 2459, 3280, 3039, 2560, 1521, 821, 822, 2253, 1319, 1321, ,2630, 2631, 2268, 3058, 2984, 2104, 2144, 2040, 2311, 2279, see copyright note) and RSA Data Security Public-Key Cryptography Standards (PKCS#1,3,5,7,8,9,10,12, see copyright note).

IAIK-JCE 3.1 with IAIK-JCE CC Core 3.1, (c) 1997-2004 IAIK