iaik.pkcs.pkcs7
Class EncryptedDataStream

java.lang.Object
  |
  +--iaik.pkcs.pkcs7.EncryptedDataStream
All Implemented Interfaces:
ContentStream
Direct Known Subclasses:
EncryptedData

public class EncryptedDataStream
extends Object
implements ContentStream

This class represents the stream-supporting implementation of the PKCS#7 EncryptedData type.

Each PKCS#7 content type is associated with a specific object identifier, derived from:

 pkcs-7 OBJECT IDENTIFIER ::=
   { iso(1) member-body(2) US(840) rsadsi(113549)
       pkcs(1) 7 }
 

The object identifier for the EncryptedData content type is defined as:

encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 }

which corresponds to the OID string "1.2.840.1.113549.1.7.6".

The PKCS#7 Cryptographic Message Standard specifies the EncryptedData content type for providing a syntax for building encrypted contents. The encrypted-data content type consists of encrypted content of any type (Version 1.5):

 EncryptedData ::= SEQUENCE {
    version Version,
    encryptedContentInfo EncryptedContentInfo }
 

The encryptedContentInfo field specifies the type of the content being encrypted, the content-encryption algorithm used for encrypting the content, and the result of the content encryption. If the encrypted content value is not present in the encryptedContent field, it has to be supplied by other means:

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

The key that is used for encrypting the content is not included in the EncryptedData structure, it is assumed to be managed by other means.


When creating a new EncryptedDataStream instance the encrypted content has to be supplied as EncryptedContentInfoStream object.

Example:

 //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);
 //create an EncryptedDataStream for the EncryptedContentInfoStream:
 EncryptedDataStream encrypted_data = new EncryptedDataStream(eci);
 //DER encode the EncryptedDataStream structure and write the encoding to an
 //output stream:
 OutputStream encoded_stream = ...;
 int blockSize = ...;
 encrypted_data.writeTo(encoded_stream, blockSize);
 
If a positive blocksize is specified, the encrypted content of the inherent EncryptedContentInfoStream will be encoded 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).

Decrypting goes the reverse way: From the DER encoded encryptedData a new EncryptedDataStream is created and parsed for the inherent EncryptedContentInfoStream. From the EncryptedContentInfoStream the encrypted content is obtained and decrypted using the same secret key:

 EncryptedDataStream encryptedData = new EncryptedDataStream(encoded_stream);
 EncryptedContentInfoStream eci =  (EncryptedContentInfoStream)encryptedData.getEncryptedContentInfo();
 //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
 }
 


This class additonally supports specific constructors and methods allowing to easily use the EncryptedData content type for password based encrypting data -- the intended usage of PKCS#7 EncryptedData. Please remark that the follwoing proceeding only may be used when doing a password based encryption. In all other situations you have to follow the way described above. However, you also may create your own EncryptedContentInfoStream even when doing a PBE encryption.

If you want to use PBE encryption but not creating an EncryptedContentInfoStream by yourself you first have to supply the data to be read from an inputstream, subsequently setup the cipher for PBE-encryption and finally call a writeTo method for encoding the EncryptedData object to a stream:

  1. Use the EncryptedDataStream(InputStream is, int blockSize) constructor for creating a new EncryptedDataStream object and supplying the data to be encrypted from an inputstream. You optionally may define a particular blockSize value for splitting the encoding of the encrypted content:
         //the data to be encrypted supplied from an input stream:
         InputStream dataStream = ...;
         // the block size:
         int blockSize = ...;
         EncryptedDataStream encrypted_data = new EncryptedDataStream(dataStream, blockSize);
         
  2. Setup the cipher for encryption by calling method setupCipher(AlgorithmID contentEA, char[] password) thereby specifying the PBE-algorithm to be used and the password, e.g.:
         AlgorithmID pbeAlgorithm = AlgorithmID.pbeWithSHAAnd3_KeyTripleDES_CBC;
         char[] password = ...;
         encrypted_data.setupCipher(pbeAlgorithm, password);
         
  3. Use a proper writeTo method for BER encoding the EncryptedData object and writing it to an output stream. If not yet done you optionally may specify a particular block size for splitting the encoding of encrypted content.
         int blockSize = ...;
         OutputStream encoded_stream = ...;
         encrypted_data.writeTo(encoded_stream, blockSize);
         
    respectively
         encryptped_data.writeTo(encoded_stream);
         
    It is recommended to use a positive block size value, because it is the intended purpose of this stream-supporting EncryptedData implementation to handle large amounts of data. When no block size is specified whole the encrypted content is encoded as primitive definite octet string, which advantageously may be done when using the non-stream supporting EncryptedData implementation. When a positve block size is specified for encoding the EncryptedData to a stream, the encrypted content is BER encoded as indefinite constructed octet string being composed of a series of definite primitive encoded octet strings of blockSize length.
For parsing the EncryptedData object and recovering the original content, first use the EncryptedDataStream(InputStream is) constructor to parse the internal structure. Before reading the recovered content by means of the getInputStream method, the cipher has to be initialized for decryption with the password by calling the setupCipher(char[] password) method:
  1. If the EncryptedData is supplied as DER encoding, first decode it to an ASN1Object:
         ASN1Object obj = DerCoder.decode(encoding);
         
  2. Create an EncryptedData structure from the supplied ASN.1 object, and parse the internal structure:
         EncryptedData encrypted_data = new EncryptedData(obj);
         
  3. Get information about the inherent EncryptedContentInfo:
         EncryptedContentInfoStream eci = (EncryptedContentInfoStream)encrypted_data.getEncryptedContentInfo();
         System.out.println("Content type: "+eci.getContentType().getName());
         System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
         
  4. Specify the passord for initializing the cipher for encrypted-content decryption:
         char[] password = ...;
         encrypted_data.setupCipher(password);
         
    Unlike the non-stream supporting EncryptedData class where the encrypted-content decryption already is performed inside the setupCipher method, the cipher will be only initialized for decryption in this class. The encrypted-content decryption actually is done during reading the data obtained by calling the getInputStream method. So donīt call getInputStream before setting up the cipher!

  5. Get and read the recovered content:
         InputStream data_is = encrypted_data.getInputStream();
         byte[] buf = new byte[1024];
         int r;
         while ((r = data_is.read(buf)) > 0) {
            // do something useful
         }
         

Version:
File Revision 27
See Also:
EncryptedContentInfoStream

Field Summary
protected  int block_size
          The block size for block oriented stream encoding.
protected  int version
          This class implements version 0 of the standard
 
Constructor Summary
protected EncryptedDataStream()
          Default constructor for dynamic object creation in ContentInfo.
  EncryptedDataStream(EncryptedContentInfoStream encryptedContentInfo)
          Creates a PKCS#7 EncryptedDataStream from an EncryptedContentInfoStream.
  EncryptedDataStream(InputStream is)
          Creates a new EncryptedDataStream where the DER encoded data is read from the given InputStream.
  EncryptedDataStream(InputStream is, int blockSize)
          Creates a new PKCS#7 EncryptedDataStream object where the content to be encrypted is read from the supplied InputStream.
 
Method Summary
 void decode(InputStream is)
          Reads and decodes the EncryptedDataStream from a DerInputStream.
 int getBlockSize()
          Gets the block size defining the length of each definite primitive encoded octet string component.
 ObjectID getContentType()
          Returns the content type this class implements.
 Object getEncryptedContentInfo()
          Returns the encrypted content info of this EncryptedDataStream object.
 InputStream getInputStream()
          Returns an InputStream from where the decrypted data can be read.
 int getVersion()
          Returns the syntax version number.
 void setBlockSize(int blockSize)
          Sets the block size for defining the length of each definite primitive encoded octet string component.
 void setupCipher(AlgorithmID contentEA, char[] password)
          Setups the cipher for PBE-encrypting the content.
 void setupCipher(AlgorithmID contentEA, char[] password, int iterationCount)
          Setups the cipher for PBE-encrypting the content.
 void setupCipher(char[] password)
          Uses the given password to setup the cipher for decrypting the content.
 ASN1Object toASN1Object()
          Returns this PKCS#7 EnvelopedDataStream as ASN1Object.
protected  ASN1Object toASN1Object(int blockSize)
          Returns this PKCS#7 EncryptedDataStream as ASN1Object where a constructed OCTET STRING is used for encoding the encrypted content.
 String toString()
          Returns a string giving some information about this EncryptedDataStream object.
 String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this EncryptedDataStream object.
 void writeTo(OutputStream os)
          BER encodes and writes this EnvelopedDataStream to the supplied output stream.
 void writeTo(OutputStream os, int blockSize)
          Writes this object to the supplied output stream where a constructed OCTET STRING is used for encoding the content.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

version

protected int version
This class implements version 0 of the standard

block_size

protected int block_size
The block size for block oriented stream encoding.
Constructor Detail

EncryptedDataStream

protected EncryptedDataStream()
Default constructor for dynamic object creation in ContentInfo. The block size is set to 2048.

EncryptedDataStream

public EncryptedDataStream(EncryptedContentInfoStream encryptedContentInfo)
Creates a PKCS#7 EncryptedDataStream from an EncryptedContentInfoStream.
Parameters:
encryptedContentInfo - the already created encrypted content info

EncryptedDataStream

public EncryptedDataStream(InputStream is,
                           int blockSize)
Creates a new PKCS#7 EncryptedDataStream object where the content to be encrypted is read from the supplied InputStream. The content type is set to PKCS#7 Data.

This constructor only shall be used when intending to PBE encrypt the data by subsequently calling method setupCipher thereby supplying PBE-algorithm and password to be used.
This constructor shall not be used in situations where the desired content encryption algorithm is not a PBE algorithm. In such cases the EncryptedDataStream(EncryptedContentInfoStream) constructor shall be used to be supplied with a precomputed EncryptedContentInfo. Consult the EncryptedContentInfoStream class documentation for more information about EncryptedContentInfo handling.

Parameters:
is - the InputStream containing the data to encrypt
blockSize - for defining the encoding scheme and setting the octet string component length, if positive

EncryptedDataStream

public EncryptedDataStream(InputStream is)
                    throws IOException,
                           PKCSParsingException
Creates a new EncryptedDataStream where the DER encoded data is read from the given InputStream.
Parameters:
is - the InputStream holding a DER encoded PKCS#7 EncryptedDataStream 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

setBlockSize

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

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.
Specified by:
getBlockSize in interface ContentStream
Returns:
blockSize defining the encoding scheme and setting the octet string component length, if positive
See Also:
OCTET_STRING

decode

public void decode(InputStream is)
            throws IOException,
                   PKCSParsingException
Reads and decodes the EncryptedDataStream from a DerInputStream. If the supplied InputStream actually is not an instance of DerInputStream, internally a DerInputStream is created before parsing the data.
Specified by:
decode in interface ContentStream
Parameters:
is - the InputStream holding a DER encoded PKCS#7 EncryptedDataStream 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,
                        char[] password)
                 throws NoSuchAlgorithmException,
                        InvalidKeyException
Setups the cipher for PBE-encrypting the content. This method only may be used to setup the cipher for PBE-encrypting the content that has been supplied when creating the EncryptedDataStream object by means of the EncryptedDataStream(InputStream is, int blockSize) constructor. The content encryption actually is performed during the encoding when writing this EncyrptedData to a stream by calling the writeTo method. So it is important to setup the cipher before writing to the stream!

Parameters:
contentEA - the PBE-algorithm to be used
password - the password
Throws:
NoSuchAlgorithmException - if the algorithm is not supported
InvalidKeyException - if the key cannot be derived from the password

setupCipher

public void setupCipher(AlgorithmID contentEA,
                        char[] password,
                        int iterationCount)
                 throws NoSuchAlgorithmException,
                        InvalidKeyException
Setups the cipher for PBE-encrypting the content. This method only may be used to setup the cipher for PBE-encrypting the content that has been supplied when creating the EncryptedDataStream object by means of the EncryptedDataStream(InputStream is, int blockSize) constructor. The content encryption actually is performed during the encoding when writing this EncyrptedData to a stream by calling the writeTo method. So it is important to setup the cipher before writing to the stream!

This method has an additional parameter: iterationCount. When deriving the symmetric key and the IV a hash is calculated iterationCount times on the password and on the salt thus increasing the cost for breaking the cipher using brute force methods.

Parameters:
contentEA - the PBE-algorithm to be used
password - the password
iterationCount - the iteration count for key derivation
Throws:
NoSuchAlgorithmException - if the algorithm is not supported
InvalidKeyException - if the key cannot be derived from the password

setupCipher

public void setupCipher(char[] password)
                 throws NoSuchAlgorithmException,
                        InvalidAlgorithmParameterException,
                        InvalidParameterSpecException,
                        InvalidKeyException
Uses the given password to setup the cipher for decrypting the content.

Unlike the non-stream supporting EncryptedData class where the encrypted-content decryption already is performed inside the setupCipher method, the cipher will be only initialized for decrypting in this class. The encrypted-content decryption actually is done during reading the data obtained by calling the getInputStream method. So donīt call getInputStream before setting up the cipher!

Attention! This method only can be used when the content has been encrypted using a PBE cipher. Otherwise the setupCipher(Key key, AlgorithmParameterSpec) method of the EncryptedContentInfoStream class has to be used to setup the cipher for content decryption.

Parameters:
password - the password
Throws:
NoSuchAlgorithmException - if the algorithm is not supported
InvalidKeyException - if the key cannot be derived from the password
InvalidAlgorithmParameterException - if the paramters cannot be retrieved from the algorithm ID
InvalidParameterSpecException - if the paramters cannot be set up

getContentType

public ObjectID getContentType()
Returns the content type this class implements.
Specified by:
getContentType in interface ContentStream
Returns:
ObjectID.pkcs7_encryptedData

getVersion

public int getVersion()
Returns the syntax version number.
Returns:
the syntax version number

getInputStream

public InputStream getInputStream()
Returns an InputStream from where the decrypted data can be read. Attention! The stream only may be read once.

When having created a new EncryptedDataStream 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 a writeTo method).
When having decoded and parsed a received EnvelopedDataStream object comimg from some stream, this method may be used for obtaining the raw (decrypted) data after having setup the cipher (if PBE-encryption is used).

Returns:
an InputStream for reading the decrypted data

toASN1Object

public ASN1Object toASN1Object()
                        throws PKCSException
Returns this PKCS#7 EnvelopedDataStream as ASN1Object.
Specified by:
toASN1Object in interface ContentStream
Returns:
this EnvelopedData as ASN1Object.
Throws:
PKCSException - if the ASN1Object could not be created

toASN1Object

protected ASN1Object toASN1Object(int blockSize)
                           throws PKCSException
Returns this PKCS#7 EncryptedDataStream as ASN1Object where a constructed OCTET STRING is used for encoding the encrypted content.
Parameters:
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Returns:
this PKCS#7 EncryptedDataStream as ASN1Object
Throws:
PKCSException - if the ASN1Object could not be created

writeTo

public void writeTo(OutputStream os)
             throws IOException
BER encodes and writes this EnvelopedDataStream to the supplied output stream.
Parameters:
os - the output stream to which this EnvelopedDataStream shall be written

writeTo

public void writeTo(OutputStream os,
                    int blockSize)
             throws IOException
Writes this object to the supplied output stream where a constructed OCTET STRING is used for encoding the content. If a positive blocksize is specified, the encrypted content of the inherent EncryptedContentInfoStream will be encoded 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).

Parameters:
os - the output stream to which this SignedData shall be written
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Throws:
IOException - if an error occurs during writing the object

getEncryptedContentInfo

public Object getEncryptedContentInfo()
Returns the encrypted content info of this EncryptedDataStream object. When calling this method for obtaining the inherent EncryptedContentInfoStream an explicit cast to EncryptedContentInfoStream has to be made:
 EncryptedContentInfoStream eci = (EncryptedContentInfoStream)encrypted_data.getEncryptedContentInfo();
 
Returns:
the EncryptedContentInfoStream

toString

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

toString

public String toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this EncryptedDataStream object.
Specified by:
toString in interface ContentStream
Parameters:
detailed - - whether or not to give detailed information
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