iaik.pkcs.pkcs7
Class ContentInfoStream

java.lang.Object
  |
  +--iaik.pkcs.pkcs7.ContentInfoStream

public class ContentInfoStream
extends Object

This class represents the stream implemention of the PKCS#7 ContentInfo type.

The PKCS#7 standard describes a general syntax for data that may have cryptography applied to it, such as digital signatures and digital envelopes.

The ASN.1 type ContentInfo type associates a content type (data, signedData, envelopedData, signedAndEnvelopedData, digestedData, encryptedData) with some particular content for specifying a general syntax for content exchanged between entities according the PKCS#7 standard:

 ContentInfo ::= SEQUENCE {
    contentType ContentType,
    content
      [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
 
ContentType ::= OBJECT IDENTIFIER

If the optional content is not present, the content value has to be supplied by other means.

This class consists of two parts: the first static part implements a factory for registering all the stream implementations of the several PKCS#7 content types. And the second non-static part provides constructors and methods for creating, en- and decoding stream PKCS#7 content type objects in the usual way.

The non-stream supporting equivalent to this class is implemented by the ContentInfo class.

When creating a new ContentInfo to be sent use the ContentInfoStream(ContentStream) constructor and subsequently call the toASN1Object or writeTo method, e.g.:

 // create a PKCS#7 object, e.g. Data:
 DataStream data = ...;
 ...
 // create a ContentInfo for the PKCS#7 object and encode it to a stream:
 ContentInfoStream cis = new ContentInfoStream(data);
 OutputStream encoded_stream = ...;
 cis.writeTo(encoded_stream);
 
However, if you want to sent a ContentInfo without any content, you only have to supply the content type identifier when creating a ContentInfoStream object, e.g.:
 ContentInfoStream cis = new ContentInfoStream(ObjectID.pkcs7_data);
 cis.writeTo(encoded_stream);
 
For parsing an already existing BER encoded ContentInfo object supplied from an input stream, use the ContentInfoStream(Inputstream) constructor. This will invoke the decode method for starting the decoding procedure. The decode method only parses the contentType object identifier and lets the content itself unparsed. This provides the possibility for getting the unparsed content by means of the getContentInputStream method. This will give you the possibility of doing the decoding and parsing by yourself. Alternatively you may call the getContent method for getting the content as ContentStream descendant. Actually when calling getContent the encoded content will be decoded and parsed for its internal structure. However, it is essential to remember that this is a stream implementation, so using both getContent and getContentInputStream would not work!

The different usage may be illustrated by means of the two types of a SignedData message. When receiving a ContentInfo holding an implicit message the content is included in the SignedData object, and so the getContent method may be appropriate for getting the already parsed SignedData content, e.g.:

 // create a ContentInfoStream from the encoding:
 ContentInfoStream cis = new ContentInfoStream(encodedStream);
 // ask for the content type:
 if (cis.getContentType().equals(ObjectID.pkcs7_signedData)) {
    // get the SignedData content:
    SignedDataStream signedData = (SignedDataStream)cis.getContent()
    // proceed as usual for reading the data, getting the SignerInfos and
    // verifying the signatures
 } else {
    throw new PKCSParsingException("Error! Expected content type SignedData!");
 }
 
However, when receiving a ContentInfo holding an explicit message where the content is not included in the SignedData object, you may want to use the the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor for initializing a SignedDataStream object with raw content and hash algorithms in the usual way, and subsequently decode the received SignedData object by feeding the decode method with the DER encoded SignedData object obtained from the ContentInfo by calling the getContentInputStream method, e.g.:
 // the raw data received by other means, supplied from an input stream:
 InputStream data_is = ...;
 // the hash algorithms (e.g. parsed from the headers of a S/MIME multipart/signed entity):
 AlgorithmID[] algIDs = { AlgorithmID.sha1, AlgorithmID.md5 };
 // the DER encoded content info, supplied from an input stream:
 InputStream encoded_stream = ...;
 // create a SignedDataStream object from raw data and hash algorithms:
 SignedDataStream signed_data = new SignedDataStream(data_is, algIDs);
 // create a ContentInfoStream from the DER encoding:
 ContentInfoStream cis = new ContentInfoStream(encoded_stream);
 // check the content type:
 if (cis.getContentType().equals(ObjectID.pkcs7_signedData)) {
    // now decode the DER encoded SignedData obtained from the ContentInfo:
    signed_data.decode(cis.getContentInputStream());
 } else {
    throw new PKCSParsingException("Error! Expected a SignedData content!");
 }
 // proceed as usual for reading the content, getting SignerInfos and verifying signatures
 ...
 
Attention! After using the getContentInputStream method for getting the unparsed content an application might not further access the corresponding ContentInfoStream object. When getting and reading the unparsed content in the way described above, the stream holding the DER encoded content will be read outside this class for decoding and parsing the inherent content. It is quite obviously that in this case the content component of the corresponding ContentInfoStream object will remain empty, unless you explicitly set it again by using the setContent(ContentStream content) method.

Version:
File Revision 28
See Also:
DataStream, DigestedDataStream, EncryptedDataStream, EnvelopedDataStream, SignedAndEnvelopedDataStream, SignedDataStream, ContentStream

Constructor Summary
ContentInfoStream(ContentStream content)
          Creates a PKCS#7 ContentInfoStream from the given content value.
ContentInfoStream(InputStream is)
          Creates a new ContentInfoStream where the DER encoded data is read from the given InputStream.
ContentInfoStream(ObjectID contentType)
          Creates an empty PKCS#7 ContentInfoStream from the given content type.
 
Method Summary
static ContentStream create(ObjectID oid)
          Returns a stream-supporting instance of the specified PKCS#7 content type implementation, defined by its ASN.1 ObjectID.
static ContentStream create(ObjectID oid, InputStream is)
          Returns a stream-supporting instance of the specified PKCS#7 content type implementation, defined by its ASN.1 ObjectID.
protected  void decode(DerInputStream is)
          Reads and decodes the ContentInfo from a DerInputStream.
 void destroyCriticalData()
          Destroys the critical data of this object.
 ContentStream getContent()
          Returns the content of this PKCS#7 ContentInfoStream.
 InputStream getContentInputStream()
          Returns the unparsed content of this PKCS#7 ContentInfo as DER encoding.
 ObjectID getContentType()
          Returns the content type of this PKCS#7 ContentInfoStream.
 boolean hasContent()
          Returns true if this ContentInfoStream has a content.
static void register(ObjectID oid, Class cls)
          Registers a new implementation for a ContentStream defined through the given ObjectID.
 void setContent(ContentStream content)
          Sets the content of this ContentInfo.
 ASN1Object toASN1Object()
          Returns this PKCS#7 ContentInfoStream as ASN1Object.
 String toString()
          Returns a string giving some information about this PKCS#7 ContentInfoStream.
 String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this PKCS#7 ContentInfoStream.
 void writeTo(OutputStream os)
          Writes the DER 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

ContentInfoStream

public ContentInfoStream(ContentStream content)
Creates a PKCS#7 ContentInfoStream from the given content value.

The content type object identifier internally is derived from the given ContentStream object by using the getContentType method.

Parameters:
content - the content object as ContentStream descendant.
See Also:
ContentStream.getContentType()

ContentInfoStream

public ContentInfoStream(ObjectID contentType)
Creates an empty PKCS#7 ContentInfoStream from the given content type.

Since no content is specified, it is set to null. The content value may be supplied by other means.

Parameters:
contentType - the type of the content, as ObjectID

ContentInfoStream

public ContentInfoStream(InputStream is)
                  throws IOException,
                         PKCSParsingException
Creates a new ContentInfoStream where the DER encoded data is read from the given InputStream. Attention!This constructor calls the decode method for initializing the decoding procedure. The decode method only parses the contentType object identifier and lets the content itself unparsed. This provides the possibility for getting the unparsed content by means of the getContentInputStream method. Alternatively you may call the getContent method for getting the content as ContentStream descendant. Actually when calling getContent the encoded content will be decoded and parsed for its internal structure. However, it is essential to remember that this is a stream implementation, so using both getContent and getContentInputStream would not work!
Parameters:
is - the InputStream holding a DER encoded PKCS#7 ContentInfo 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

create

public static ContentStream create(ObjectID oid)
                            throws PKCSException
Returns a stream-supporting instance of the specified PKCS#7 content type implementation, defined by its ASN.1 ObjectID. This method belongs to the static part of this class.

Parameters:
oid - the ObjectID of the extension.
Returns:
the stream implementation of the PKCS#7 content, identified by the given OID
Throws:
PKCSException - if an error occurs when creating the PKCS#7 ContentStream object

create

public static ContentStream create(ObjectID oid,
                                   InputStream is)
                            throws IOException,
                                   PKCSParsingException
Returns a stream-supporting instance of the specified PKCS#7 content type implementation, defined by its ASN.1 ObjectID. The new instance will be initialized with the given InputStream.

This method belongs to the static part of this class.

Parameters:
oid - the ObjectID of the PKCs#7 content
is - an InputStream holding a DER encoded version of the content specified through the oid
Returns:
the initialized stream implementation of the PKCS#7 content with this oid
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object

register

public static void register(ObjectID oid,
                            Class cls)
Registers a new implementation for a ContentStream defined through the given ObjectID.

This method registeres the given class as stream-supporting implementation of the supplied PKCS#7 content type. The content type has to be specified by its ObjectID. This method belongs to the static part of this class.

Parameters:
oid - the object id of the PKCS#7 content type to be registered
cls - the stream implementing class

decode

protected void decode(DerInputStream is)
               throws IOException,
                      PKCSParsingException
Reads and decodes the ContentInfo from a DerInputStream. If the supplied InputStream actually is not an instance of DerInputStream, internally a DerInputStream is created before parsing the data. Attention! This method only parses the contentType object identifier and lets the content itself unparsed. This provides the possibility for getting the unparsed content by means of the getContentInputStream method. Alternatively you may call the getContent method for getting the content as ContentStream descendant. Actually when calling getContent the encoded content will be decoded and parsed for its internal structure. However, it is essential to remember that this is a stream implementation, so using both getContent and getContentInputStream would not work!
Parameters:
is - the InputStream holding a DER encoded PKCS#7 ContentInfoStream object
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object

toASN1Object

public ASN1Object toASN1Object()
                        throws PKCSException
Returns this PKCS#7 ContentInfoStream as ASN1Object.
Returns:
this PKCS#7 ContentInfoStream as ASN1Object

writeTo

public void writeTo(OutputStream os)
             throws IOException,
                    PKCSException
Writes the DER encoding of this object to the given OutputStream. The ContentInfo structure is encoded as ASN.1 SEQUENCE using the indefinite length encoding scheme:
 30 80
    ...
    ...
 00 00
 
Parameters:
os - the OutputStream where 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

hasContent

public boolean hasContent()
Returns true if this ContentInfoStream has a content.
Returns:
true if this ContentInfoStream has a content

getContent

public ContentStream getContent()
                         throws IOException,
                                PKCSParsingException
Returns the content of this PKCS#7 ContentInfoStream. If called during a parsing process this method actually will decode and parse the BER encoded content. For that reason this method must throw an IOException and a PKCSParsingException if some error occurs during the parsing procedure.

For getting the unparsed DER encoded content as, you may call the getContentInputStream method. This will give you the possibility of doing the decoding and parsing by yourself. However, since this is a stream implementation, remember that you can read the stream only once! For that reason you never should use both methods getContent and getContentInputStream!

Returns:
the content value as ContentStream descendant
Throws:
IOException - if some error occurs while reading from the stream supplying the DER encoded content
PKCSParsingException - if an error occurs during parsing the content

getContentInputStream

public InputStream getContentInputStream()
Returns the unparsed content of this PKCS#7 ContentInfo as DER encoding. This method may be used for getting the DER encoding of the content for further processing it by the corresponding content implementing class itself. In this way, this method only shall be used as part of the parsing process; otherwise it will return null.

This method may be useful for parsing an explicit SignedData object that has been wrapped into a ContentInfo. You can use the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) in the normal way for initializing a SignedDataStream object with raw content and hash algorithms, and subsequently decode the received SignedData object by feeding the decode method with the DER encoded SignedData object obtained from the ContentInfo by calling this getContentInputStream method, e.g.:

 // the raw data received by other means, supplied from an input stream:
 InputStream data_is = ...;
 // the hash algorithms (e.g. parsed from the headers of a S/MIME multipart/signed entity):
 AlgorithmID[] algIDs = { AlgorithmID.sha1, AlgorithmID.md5 };
 // the DER encoded content info, supplied from an input stream:
 InputStream der_stream = ...;
 // create a SignedDataStream object from raw data and hash algorithms:
 SignedDataStream signed_data = new SignedDataStream(data_is, algIDs);
 // create a ContentInfoStream from the DER encoding:
 ContentInfoStream cis = new ContentInfoStream(der_stream);
 // check the content type:
 if (cis.getContentType().equals(ObjectID.pkcs7_signedData)) {
    // now decode the DER encoded SignedData obtained from the ContentInfo:
    signed_data.decode(cis.getContentInputStream());
 } else {
    throw new PKCSParsingException("Error! Expected a SignedData content!");
 }
 // proceed as usual for reading the content, getting SignerInfos and verifying signatures
 ...
 
Attention! After using this method for getting the unparsed content an application might not further access the corresponding ContentInfoStream object. When getting and reading the unparsed content in the way described above, the stream holding the DER encoded content will be read outside this class for decoding and parsing the inherent content. It is quite obviously that in this case the content component of the corresponding ContentInfoStream object will remain empty, unless you explicitly set it again by using the setContent(ContentStream content) method.

For parsing and getting the content as ContentStream descendant, you may call the getContent method. However, since this is a stream implementation, you never should use both methods getContent and getContentInputStream!

Returns:
the content value as Content descendant

getContentType

public ObjectID getContentType()
Returns the content type of this PKCS#7 ContentInfoStream.
Returns:
the content type, as ObjectID

setContent

public void setContent(ContentStream content)
Sets the content of this ContentInfo.

The content type object identifier internally is derived from the given ContentStream object by using the getContentType method.

Parameters:
content - the content object as ContentStream descendant.

destroyCriticalData

public void destroyCriticalData()
Destroys the critical data of this object.

toString

public String toString()
Returns a string giving some information about this PKCS#7 ContentInfoStream.
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 PKCS#7 ContentInfoStream.
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