iaik.cms
Class DigestedDataStream

java.lang.Object
  extended by iaik.cms.DigestedDataStream
All Implemented Interfaces:
EncodeListener, ContentStream, EOFListener, java.util.EventListener
Direct Known Subclasses:
DigestedData

public class DigestedDataStream
extends java.lang.Object
implements ContentStream, EncodeListener, EOFListener

This class represents the stream supporting implementation of the CMS DigestedData type.

Each CMS 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 DigestedData content type is defined as:

digestedData OBJECT IDENTIFIER ::= { pkcs-7 5 }

which corresponds to the OID string "1.2.840.113549.1.7.5".

The Cryptographic Message Syntax (CMS) (RFC 5652) specifies the DigestedData content type for providing a syntax for building message digests. The digested-data content type consists of content of any type and a message digest of the content:

 DigestedData ::= SEQUENCE {
    version            Version,
    digestAlgorithm    DigestAlgorithmIdentifier,
    encapContentInfo   EncapsulatedContentInfo,
    digest             Digest }
 
Digest ::= OCTET STRING

The digestAlgorithm field specifies the digest algorithm to be used for computing the message digest of the content given in the encapContentInfo field. The result of the digest calculation is stored in the digest field. Verifying a received message digest is done by comparing it with an independently computed message digest.


When creating a DigestedDataStream object for the content to be digested by using the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm, int mode) constructor, additionally the transimission mode has to be specified. If the mode is set to DigestedDataStream.IMPLICIT the raw data will be included in the DigestedData message to be transmitted, but it will be not included if the mode is set to DigestedDataStream.EXPLICIT. However, in both cases the raw data has to be supplied when creating the DigestedDataStream object, because it is needed for the digest computation:

 InputSrteam data_stream = ...; // the raw data supplying input stream
 AlgorithmID digestAlg = ...;
 DigestedDataStream digested_data = new DigestedDataStream(data_stream, digestAlg, DigestedDataStream.IMPLICIT);
 
respectively
 DigestedDataStream digested_data = new DigestedDataStream(data_stream, digestAlg, DigestedDataStream.EXPLICIT);
 
In contrast to the non-stream-variant of the CMS DigestedData type (implemented by the DigestedData class), where explicit and implicit mode can be handled in the same way when creating a DigestedData object, they require a different proceeding for the stream-supporting DigestedDataStream class. In this way, the steps for creating a DigestedDataStream object and preparing it for transmission can be summarized in the following way:
  1. Create a new DigestedDataStream object thereby supplying the raw data to be digested as input stream and specifying digest algorithm and transmission mode to be used (either DigestedDataStream.IMPLICIT or DigestedDataStream.EXPLICIT):
         InputStream data_stream = ...;
         int mode = ...;
         AlgorithmID digestAlg = ...;
         DigestedDataStream digested_data = new DigestedDataStream(data_stream, digestAlg, mode);
         
  2. If the chosen mode is DigestedDataStream.EXPLICIT, now get and read the data from the data carrying input stream. Since in explicit mode the raw data is not included in the DigestedData message, the stream has to be read before actually performing the encoding. When reading the stream, the data is piped a digest stream for updating the hash computation.
         if (mode == DigestedDataStream.EXPLICIT) {
           InputStream data_is = digested_data.getInputStream();
           byte[] buf = new byte[2048];
           int r;
           while ((r = data_is.read(buf)) > 0) {
             // do something useful
           }
         }
         
    When using the implicit mode, do not explicitly read data from the input stream at all! This will be done automatically during the last step when performing the encoding.

  3. Use a proper writeTo method for BER encoding the the DigestedDataStream object and writing it to an output stream. You optionally may specify a particular block size for splitting the data encoding:
         int blockSize = ...;
         digested_data.writeTo(output_stream, blockSize);
         
    respectively
         digested_data.writeTo(output_stream);
         
    It is recommended only to use the writeTo method where a particular block size can be specified, because it is the intended purpose of this stream-supporting DigestedData implementation to handle large amounts of data. When no block size is specified whole the raw data is encoded as one primitive definite octet string, which advantageously may be done when using the non-stream supporting DigestedData implementation. When a positive block size is specified for encoding the DigestedData to a stream, the raw data is BER encoded as indefinite constructed octet string being composed of a series of definite primitive encoded octet strings of blockSize length, e.g.:
         0x24 0x80
                   0x04 0x02 0x01 0xAB
                   0x04 0x02 0x23 0x7F
                   0x04 0x01 0xCA
         0x00 0x00
         
    instead of:
         0x04 0x05 0x01 0xAB 0x23 0x7F 0xCA
         
    for encoding the five data bytes 0x01 0xAB 0x23 0x7F 0xCA.

Again, it has to be distinguished between IMPLICIT and EXPLICIT mode when using the DigestedDataStream implementation for parsing a received DigestedData message. When operating in IMPLICIT mode, the raw data is included in the received DigestedData object, and so the parsing immediately may be performed when creating a DigestedDataStream object from the BER encoded DigestedData object by calling the DigestedDataStream(InputStream is) constructor. On the other side, when the raw data has been transmitted outside the DigestedData message (EXPLICIT mode), the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm) constructor has to be used for initializing the new DigestedDataStream object with raw data and hash algorithm to be used for digest computation; and the decoding has to be performed explicitly by calling the decode method. The initialization is necessary for preparing the digest computation on the raw data for the specified digest algorithm. Later, during digest verification the digest value computaion is finished and the result is compared against the hash value sent within the final digest field.
The individual steps necessary for parsing a received DigestedData message and verifying the digest may be summarized as follows:

  1. If the InputStream supplies the BER encoding of an implicit DigestedData object, use the DigestedDataStream(InputStream is) constructor for creating a DigestedDataStream object and implicitly performing the decoding:
         DigestedDataStream digestedData = new DigestedDataStream(encoded_stream);
         
    On the other hand, if the BER encoding represents an explicit DigestedData object, use the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm) constructor for initializing a new DigestedDataStream object with raw data and digest algorithm for hash computation (assuming that the hash algorithm is SHA-256):
         AlgorithmID algID = AlgorithmID.sha256;
         DigestedDataStream digestedData = new DigestedDataStream(data_is, algID);
         
  2. Get the data carrying input stream and entirely read the data from the stream. This has to be performed for both implicit and explicit modes at exactly this state of the parsing procedure. In both cases the constructor has initialized the digest computation by wrapping digest streams around the raw data stream for the given digest algorithm, either implicitly parsed from the supplied DigestedData object, or explicitly supplied as via the constructor. When now reading the stream, the data is piped through the digest stream for updating the hash computation:
         InputStream dataIs = digestedDdata.getInputStream();
         byte[] buf = new byte[2048];
         int r;
         while ((r = dataIs.read(buf)) > 0) {
           // do something useful
         }
         
  3. When dealing with an explicit message now explicitly perform the decoding by calling the decode method:
         digestedData.decode(encoded_stream);
         
  4. Now it is time to call the verify method for comparing the computed digest against the value sent in the digest field:
         if (digestedData.verify())
            System.out.println("Hash o.k!");
         else
            System.out.println("hash verification failed!");
         


Field Summary
protected  int blockSize_
          The block size for block oriented stream encoding.
protected  ObjectID contentType_
          The content type.
protected  AlgorithmID digestAlgorithm_
          The digest algorithm to use.
protected  EncapsulatedContentInfoStream encapContentInfo_
          The inherent EncapsualtedContentInfo.
static int EXPLICIT
          Denotes a mode where the data to be digested is not included.
static int IMPLICIT
          Denotes a mode where the data to be digested is included.
protected  java.io.InputStream inputStream_
          An InputStream holding the data.
protected  int mode_
          The mode specifying if the data shall be included (IMPLICIT), or if is not included (EXPLICIT).
protected  SecurityProvider securityProvider_
          The SecurityProvider to be used by this object.
protected  int version_
          The CMS version number.
 
Constructor Summary
protected DigestedDataStream()
          Default constructor for dynamic object creation in ContentInfoStream.
  DigestedDataStream(java.io.InputStream is)
          Creates a DigestedDataStream object from a BER encoded DigestedData object which is read from the given input stream.
  DigestedDataStream(java.io.InputStream data_is, AlgorithmID digestAlgorithm)
          Creates a new DigestedDataStream from an InputStream holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.
  DigestedDataStream(java.io.InputStream data_is, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedDataStream object from given content and and digest algorithm.
  DigestedDataStream(java.io.InputStream data_is, AlgorithmID digestAlgorithm, SecurityProvider securityProvider)
          Creates a new DigestedDataStream from an InputStream holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.
  DigestedDataStream(java.io.InputStream is, SecurityProvider securityProvider)
          Creates a DigestedDataStream object from a BER encoded DigestedData object which is read from the given input stream.
  DigestedDataStream(ObjectID contentType, AlgorithmID digestAlgorithm, byte[] digest)
          Creates a new DigestedDataStream object without content.
  DigestedDataStream(ObjectID contentType, java.io.InputStream data_is, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedDataStream object from given content and and digest algorithm.
  DigestedDataStream(ObjectID contentType, java.io.InputStream data_is, AlgorithmID digestAlgorithm, int mode, SecurityProvider securityProvider)
          Creates a new DigestedDataStream object from given content and and digest algorithm.
 
Method Summary
 void decode(java.io.InputStream is)
          Reads and decodes a BER encoded DigestedData from an input stream.
 void encodeCalled(ASN1Object o, int id)
          This method implements the EncodeListener interface.
 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.
 byte[] getDigest()
          Returns the message-digest computed on the content value.
 AlgorithmID getDigestAlgorithm()
          Returns the message-digest algorithm used for computing the digest.
 ObjectID getEncapsulatedContentType()
          Returns the content type the inherent EncapsulatetContentInfo represents.
 java.io.InputStream getInputStream()
          Returns an input stream from which the data may be read.
 int getMode()
          Returns the mode of this DigestedData.
 SecurityProvider getSecurityProvider()
          Gets the SecurityProvider installed for this DigestedDataStream.
 int getVersion()
          Returns the version syntax number.
 void notifyEOF()
          This method implements the EOFListener interface for performing the final decoding.
 void setBlockSize(int blockSize)
          Sets the block size for defining the length of each definite primitive encoded octet string component.
 void setDigest(byte[] digest)
          Sets the message-digest value.
 void setInputStream(java.io.InputStream is)
          Sets the InputStream which holds the content to sign/verify.
 void setSecurityProvider(SecurityProvider securityProvider)
          Sets the SecurityProvider for this DigestedDataStream.
 ASN1Object toASN1Object()
          Returns this DigestedDataStream as ASN1Object.
protected  ASN1Object toASN1Object(int blockSize)
          Returns this DigestedData as ASN1Object where a constructed OCTET STRING is used for encoding the content.
 java.lang.String toString()
          Returns a string giving some information about this DigestedData object.
 java.lang.String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this DigestedData object.
 boolean verify()
          Verifies the digest.
 void writeTo(java.io.OutputStream os)
          Writes this DigestedData DER encoded to the supplied output stream.
 void writeTo(java.io.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

IMPLICIT

public static final int IMPLICIT
Denotes a mode where the data to be digested is included.

See Also:
Constant Field Values

EXPLICIT

public static final int EXPLICIT
Denotes a mode where the data to be digested is not included.

See Also:
Constant Field Values

version_

protected int version_
The CMS version number. Default: 0.


digestAlgorithm_

protected AlgorithmID digestAlgorithm_
The digest algorithm to use.


contentType_

protected ObjectID contentType_
The content type.


blockSize_

protected int blockSize_
The block size for block oriented stream encoding. (Default: 2048 to enforce indefinite constructed encoding).


encapContentInfo_

protected EncapsulatedContentInfoStream encapContentInfo_
The inherent EncapsualtedContentInfo.


inputStream_

protected java.io.InputStream inputStream_
An InputStream holding the data.


mode_

protected int mode_
The mode specifying if the data shall be included (IMPLICIT), or if is not included (EXPLICIT).


securityProvider_

protected SecurityProvider securityProvider_
The SecurityProvider to be used by this object.

Constructor Detail

DigestedDataStream

protected DigestedDataStream()
Default constructor for dynamic object creation in ContentInfoStream. Shall be not used by an application. The block size is set to 2048 to enforce indefinite constructed encoding.


DigestedDataStream

public DigestedDataStream(java.io.InputStream data_is,
                          AlgorithmID digestAlgorithm,
                          int mode)
                   throws CMSException
Creates a new DigestedDataStream object from given content and and digest algorithm. The data to be digested is supplied as input stream. The mode parameter specifies whether to include the data (mode = DigestedDataStream.IMPLICIT) or not include it (mode = DigestedDataStream.EXPLICIT). The content type of the inherent EncapsulatedContentInfo automatically is set to CMS Data.

Parameters:
data_is - the data to be digested supplied from an input stream
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either DigestedDataStream.IMPLICIT for including the data, or DigestedDataStream.EXPLICIT for not including it
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedDataStream

public DigestedDataStream(ObjectID contentType,
                          java.io.InputStream data_is,
                          AlgorithmID digestAlgorithm,
                          int mode)
                   throws CMSException
Creates a new DigestedDataStream object from given content and and digest algorithm. The data to be digested is supplied as input stream. The mode parameter specifies whether to include the data (mode = DigestedDataStream.IMPLICIT) or not include it (mode = DigestedDataStream.EXPLICIT).

Parameters:
contentType - the content type of the data to be digested
data_is - the data to be digested supplied from an input stream
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either DigestedDataStream.IMPLICIT for including the data, or DigestedDataStream.EXPLICIT for not including it
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedDataStream

public DigestedDataStream(ObjectID contentType,
                          java.io.InputStream data_is,
                          AlgorithmID digestAlgorithm,
                          int mode,
                          SecurityProvider securityProvider)
                   throws CMSException
Creates a new DigestedDataStream object from given content and and digest algorithm. The data to be digested is supplied as input stream. The mode parameter specifies whether to include the data (mode = DigestedDataStream.IMPLICIT) or not include it (mode = DigestedDataStream.EXPLICIT).

Parameters:
contentType - the content type of the data to be digested
data_is - the data to be digested supplied from an input stream
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either DigestedDataStream.IMPLICIT for including the data, or DigestedDataStream.EXPLICIT for not including it
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedDataStream

public DigestedDataStream(ObjectID contentType,
                          AlgorithmID digestAlgorithm,
                          byte[] digest)
Creates a new DigestedDataStream object without content.

For instance:

 byte[] message = "Test data to be digested".getBytes();
 MessageDigest md = MessageDigest.getInstance("SHA-256");
 md.update(message);
 byte[] digest = md.digest();
 DigestedDataStream digested_data = new DigestedDataStream(ObjectID.cms_data, AlgorithmID.sha256, digest);
 

The content must be transferred by other means.

Parameters:
contentType - the content type of the digested data
digestAlgorithm - the message-digest algorithm (and any associated parameters) used for creating the digest
digest - the already calculated digest value

DigestedDataStream

public DigestedDataStream(java.io.InputStream is)
                   throws java.io.IOException,
                          CMSParsingException
Creates a DigestedDataStream object from a BER encoded DigestedData object which is read from the given input stream. The encoded DigestedData may (or may not) be wrapped into a ContentInfo.

The given input stream supplies the BER encoding of an already existing CMS DigestedData object. This constructor shall be used for parsing a implict DigestedData object where the content is included.
To initialize a DigestedDataStream object for parsing an explicit DigestedData message where the raw data is not included, use the DigestedDataStream(InputStream data_is, AlgorithmID hashAlgorithm) constructor, and perform the decoding explicitly by calling the decode method.

A sender shall use the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content to be digested when creating a DigestedDataStream object.

Parameters:
is - the InputStream holding the BER encoded CMS DigestedData object
Throws:
java.io.IOException - if an error occurs when reading from the stream
CMSParsingException - if the object can not be parsed

DigestedDataStream

public DigestedDataStream(java.io.InputStream is,
                          SecurityProvider securityProvider)
                   throws java.io.IOException,
                          CMSParsingException
Creates a DigestedDataStream object from a BER encoded DigestedData object which is read from the given input stream. The encoded DigestedData may (or may not) be wrapped into a ContentInfo.

The given input stream supplies the BER encoding of an already existing CMS DigestedData object. This constructor shall be used for parsing a implict DigestedData object where the content is included.
To initialize a DigestedDataStream object for parsing an explicit DigestedData message where the raw data is not included, use the DigestedDataStream(InputStream data_is, AlgorithmID hashAlgorithm) constructor, and perform the decoding explicitly by calling the decode method.

A sender shall use the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content to be digested when creating a DigestedDataStream object.

Parameters:
is - the InputStream holding the BER encoded CMS DigestedData object
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
java.io.IOException - if an error occurs when reading from the stream
CMSParsingException - if the object can not be parsed

DigestedDataStream

public DigestedDataStream(java.io.InputStream data_is,
                          AlgorithmID digestAlgorithm)
                   throws java.io.IOException
Creates a new DigestedDataStream from an InputStream holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.

Do not use this constructor for supplying the content value to be digested. This constructor may be used by the recipient for initializing the digest computation for an already existing explicit DigestedData message where the raw data is not included. The initialization is done by wrapping a digest stream around the supplied raw data stream for the specified hash algorithm. Subsequently the hash value will be updated when reading the stream thereby piping the data through the digest stream. Later, during digest verification the digest computaion is finished and the result is compared with the hash values derived parsed from the encoding.
For an explicit message the actual decoding has to be performed by calling the decode method just after reading the data:

 // initialize for hash computation:
 DigestedDataStream digestedData = new DigestedDataStream(data_is, hashAlgorithm);
 //read the stream thereby updating the hash values:
 InputStream dataIs = digestedData.getInputStream();
 byte[] buf = new byte[2048];
 int r;
 while ((r = dataIs.read(buf)) > 0) {
   // do something useful
 }
 // explicitly perform the decoding
 digestedData.decode(encoded_stream);
 

A sender shall use the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content to be digested when creating a DigestedDataStream object.

For decoding an implicit DigestedDataStream message, use the DigestedDataStream(InputStream is) constructor.

Parameters:
data_is - the InputStream supplying the raw data which has been transmitted by other means
digestAlgorithm - the hash algorithm used by for digesting the content data
Throws:
java.io.IOException - if there is no implementation for the specified hash algorithm

DigestedDataStream

public DigestedDataStream(java.io.InputStream data_is,
                          AlgorithmID digestAlgorithm,
                          SecurityProvider securityProvider)
                   throws java.io.IOException
Creates a new DigestedDataStream from an InputStream holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.

Do not use this constructor for supplying the content value to be digested. This constructor may be used by the recipient for initializing the digest computation for an already existing explicit DigestedData message where the raw data is not included. The initialization is done by wrapping a digest stream around the supplied raw data stream for the specified hash algorithm. Subsequently the hash value will be updated when reading the stream thereby piping the data through the digest stream. Later, during digest verification the digest computaion is finished and the result is compared with the hash values derived parsed from the encoding.
For an explicit message the actual decoding has to be performed by calling the decode method just after reading the data:

 // initialize for hash computation:
 DigestedDataStream digestedData = new DigestedDataStream(data_is, hashAlgorithm);
 //read the stream thereby updating the hash values:
 InputStream dataIs = digestedData.getInputStream();
 byte[] buf = new byte[2048];
 int r;
 while ((r = dataIs.read(buf)) > 0) {
   // do something useful
 }
 // explicitly perform the decoding
 digestedData.decode(encoded_stream);
 

A sender shall use the DigestedDataStream(InputStream data_is, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content to be digested when creating a DigestedDataStream object.

For decoding an implicit DigestedDataStream message, use the DigestedDataStream(InputStream is) constructor.

Parameters:
data_is - the InputStream supplying the raw data which has been transmitted by other means
digestAlgorithm - the hash algorithm used by for digesting the content data
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
java.io.IOException - if there is no implementation for the specified hash algorithm
Method Detail

setSecurityProvider

public void setSecurityProvider(SecurityProvider securityProvider)
Sets the SecurityProvider for this DigestedDataStream.

This method allows to explicitly set a SecurityProvider for this DigestedDataStream. If no explicit SecurityProvider is set, the default system wide installed SecurityProvider will be used for the required cryptographic operations.

This class may use the following method(s) of the SecurityProvider, which may be overriden by an application, if required:

An application may prefer to supply the security provider immediatey when creating the DigestDataStream object.

Parameters:
securityProvider - the SecurityProvider to be set

getSecurityProvider

public SecurityProvider getSecurityProvider()
Gets the SecurityProvider installed for this DigestedDataStream.

This class uses the following method(s) of the SecurityProvider, which may be overriden by an application, if required:

If no explicit SecurityProvider has been set for this object, the default system wide installed SecurityProvider will be used for the required cryptographic operations. However, this method will return null if it does not have its own SecurityProvider.

Returns:
the SecurityProvider explicitly installed for this object, or null if this object does not have its own SecurityProvider

decode

public void decode(java.io.InputStream is)
            throws java.io.IOException,
                   CMSParsingException
Reads and decodes a BER encoded DigestedData from an input stream. The encoded DigestedData may (or may not) be wrapped into a ContentInfo.

Specified by:
decode in interface ContentStream
Parameters:
is - the InputStream holding a BER encoded CMS DigestedData object
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

getContentType

public ObjectID getContentType()
Returns the content type this class implements.

Specified by:
getContentType in interface ContentStream
Returns:
ObjectID.cms_digestedData

getEncapsulatedContentType

public ObjectID getEncapsulatedContentType()
Returns the content type the inherent EncapsulatetContentInfo represents.

Returns:
the content type the inherent EncapsulatetContentInfo represents

getVersion

public int getVersion()
Returns the version syntax number. At this time version 0 is implemented.

Returns:
the version syntax number

getDigestAlgorithm

public AlgorithmID getDigestAlgorithm()
Returns the message-digest algorithm used for computing the digest.

Returns:
the ID of the message-digest algorithm

getDigest

public byte[] getDigest()
Returns the message-digest computed on the content value.

Returns:
the message-digest, as byte array

setDigest

public void setDigest(byte[] digest)
Sets the message-digest value. This method can be used to set a digest value that has been calculated outside this class.

Parameters:
digest - the digest value as byte array

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 DigestedData 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

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.

Specified by:
getBlockSize in interface ContentStream
Returns:
blockSize defining the encoding scheme and setting the octet string component length, if positive

getMode

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

Returns:
IMPLICIT or EXPLICIT

getInputStream

public java.io.InputStream getInputStream()
Returns an input stream from which the data may be read.

Attention! The stream only may be read once.

When having created a new DigestedDataStream object to be encoded to a stream, this method should only be called in EXPLICT mode to get and read away the content to be transmitted by other means. In IMPLICT mode this method shall not be called at all since the content has to be included in the DigestedData message (and therefore should not be read "away").
When having decoded and parsed a received DigestedDataStream object coming from some stream, this method may be used for obtaining the raw content.

Returns:
an input stream with the raw data

setInputStream

public void setInputStream(java.io.InputStream is)
                    throws CMSException
Sets the InputStream which holds the content to sign/verify.

This method may be used to supply the content data received by other means when parsing an explict DigestedData, e.g.:

 // the stream from which to read the encoded DigestedData
 InputStream digestIs = ...;
 // the stream from which to read the content received by other means
 InputStream dataIs = ...;

 // create the DigestedDataStream object tp parse the encoded DigestedData
 DigestedDataStream digestedData = new DigestedDataStream(digestIs);
 // explicit mode: set content received by other means
 digestedData.setInputStream(dataIs);

 // get and read the content
 InputStream data = digestedData.getInputStream();
 Output os = ...;
 // copy data
 Util.copyStream(data, os, null);

 // verify digest
 if (digestedData.verify()) {
   System.out.println("Hash ok!");
 } else {
   throw new Exception("Hash verification failed!");
 }
 
 

Parameters:
is - the InputSteam holding the content to sign/verify
Throws:
CMSException - if the digest algorithm used by this DigestedDataStream is not supported

toASN1Object

public ASN1Object toASN1Object()
                        throws CMSException
Returns this DigestedDataStream as ASN1Object.

Specified by:
toASN1Object in interface ContentStream
Returns:
this DigestedDataStream as ASN1Object
Throws:
CMSException - if the ASN1Object could not be created

toASN1Object

protected ASN1Object toASN1Object(int blockSize)
                           throws CMSException
Returns this DigestedData as ASN1Object where a constructed OCTET STRING is used for encoding the content.

Parameters:
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Throws:
CMSException - if the ASN1Object could not be created

encodeCalled

public void encodeCalled(ASN1Object o,
                         int id)
                  throws CodingException
This method implements the EncodeListener interface. During the encoding process the DerCoder calls this method when it actually is time for computing and setting the message digest to be encoded. In particular for the stream-supporting implementation of this DigestedData content type, the message digest cannot be computed before the content stream entirely has been read. Since the content stream actually is read during the encoding procedure, this class has to be notified when the content stream has been read. This is done by means of the IAIK-JCE EncodeListener utility. The toASN1Object() method of this DigestedDataStream class instantiates an empty OCTET_STRING for the digest field, and registers itself as EncodeListener for this empty OCTET_STRING. Now, during the encoding process, when the content stream entirely has been read, this encodeCalled method is called for performing digest computation. The supplied ASN1Object is the empty OCTET_STRING to be "filled" with the result of the digest-computation.

Specified by:
encodeCalled in interface EncodeListener
Parameters:
o - an OCTET_STRING for being supplied with the message digest value
id - the id identifying the particular octet string to be processed
Throws:
CodingException - if an error occurs when computing/encrypting the message digest

notifyEOF

public void notifyEOF()
               throws java.io.IOException
This method implements the EOFListener interface for performing the final decoding. Since the digest field is located at the end of a DigestedData structure, it only can be accessed after reading the data stream. For that reason, when starting the parsing of an implicit DigestedData message only version, digestAlgorithms, and encspContentInfo fields can be parsed before reading the data. Since the data is supplied from an input stream, an IAIK-JCE NotifyEOFInputStream is wrapped around this raw data stream for indicating that the parsing procedure is to be notified when the stream actually has been read. At that point, the programm exceuting automatically jumps to the actual notifyEOF method for finishing the decoding by parsing the final digest field.
For any application it is strongly recommended not to explicitly call this method. This method only is qualified as public method since it implements the IAIK-JCE EOFListener interface.

Specified by:
notifyEOF in interface EOFListener
Throws:
java.io.IOException - if an error occurs while parsing the stream

verify

public boolean verify()
               throws CMSException
Verifies the digest. This method finishes the hash computation on the data and compares it with the value received in the digest field.

Returns:
true if the hash verifies, false otherwise
Throws:
CMSException - if an error occurs during verification process

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException
Writes this DigestedData DER encoded to the supplied output stream. If for the inherent content structure a positive blocksize has been specified, the content is encoded as indefinite constructed octet string.

Parameters:
os - the output stream to which this DigestedData shall be written
Throws:
java.io.IOException - if an IOException occurs while writing to the stream

writeTo

public void writeTo(java.io.OutputStream os,
                    int blockSize)
             throws java.io.IOException
Writes this object to the supplied output stream where a constructed OCTET STRING is used for encoding the content. If block size has a value > 0, in implicit mode the inherent raw data is encoded as constructed OCTET STRING. In this case the encoding is splitted according to the defined block size:
 0x24 0x80
           0x04 <blocksize> <data>
           0x04 <blocksize> <data>
           0x04 <blocksize> <data>
                ...
 0x00 0x00
 
If the block size is not positive, whole the inherent data is encoded as one single primitive definite octet string:
 0x04 <length> <data>
 

Parameters:
os - the output stream to which this DigestedData 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:
java.io.IOException - if an error occurs during writing the object

toString

public java.lang.String toString()
Returns a string giving some information about this DigestedData object.

Overrides:
toString in class java.lang.Object
Returns:
the string representation

toString

public java.lang.String toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this DigestedData 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 text parts from IETF Internet Standard specifications (see copyright note).

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