iaik.cms
Class DigestedDataOutputStream

java.lang.Object
  extended by java.io.OutputStream
      extended by iaik.cms.DigestedDataOutputStream
All Implemented Interfaces:
java.io.Closeable, java.io.Flushable

public class DigestedDataOutputStream
extends java.io.OutputStream

This is an OutputStream implementation of the CMS (RFC 5652) DigestedData structure. It allows creating a digested object by writing the content to be digested to this stream.

It supports implicit (where the content is included in the DigestedData object) and explicit (where the content is transmitted by other means) DigestedData objects.

This stream version will encode the content of the DigestedData as a constructed OCTET STRING. Each write operation to this stream will result in a OCTET STRING block within this constructed OCTET STRING. Consequently, the size of each block equals the size of the data provided to the wirte operation.

The final call to close() will finish the encoding and write the digest value to the stream.

The typical usage of this class looks like this example for creating a CMS DigestedData structure with the digested content included.

   // the input stream from which to read the data to be digested
   InputStream dataInputStream = ...
   // the output stream to which to write the digested data 
   OutputStream resultStream = ...
   
   // the digest algorithm to be used  
   AlgorithmID digestAlg = AlgorithmID.sha256;
   
   // create DigestedDataOutputStream
   DigestedDataOutputStream digestedData = 
     new DigestedDataOutputStream(resultStream, digestAlg, DigestedDataOutputStream.IMPLICIT);
   
   // write in the data to be digested
   byte[] buffer = new byte[2048];
   int bytesRead;
   while ((bytesRead = dataInputStream.read(buffer)) != -1) {
     digestedData.write(buffer, 0, bytesRead);
   }
   // closing the stream calculates and writes the digest vaue and closes the underlying stream
   digestedData.close();
 
For using the DigestedDataOutputStream in explicit mode, specify DigestedDataOutputStream.EXPLICIT when creating the DigestedDataOutputStream object:
   DigestedDataOutputStream digestedData = 
     new DigestedDataOutputStream(resultStream, digestAlg, DigestedDataOutputStream.EXPLICIT);
 
The further proceeding is the same as in implicit mode. When calling a write method, the content data is dropped (since it must not be included in the DigestedData object and has to be transmitted by other means). However, piping the data through write calls is required for hash calculation.

If you want to encapsulate the DigestedData into a ContentInfo you first must wrap a ContentInfoOutputStream around the final output stream (the ContentInfoStream has to write its headers to the stream at first, thus it must be created at the "lowest" level):

   ContentInfoOutputStream contentInfoStream = 
     new ContentInfoOutputStream(ObjectID.cms_digestedData, resultStream);
   // now create DigestedDataOutputStream for the ContentInfoStream:
   DigestedDataOutputStream digestedData = 
     new DigestedDataOutputStream(contentInfoStream, digestAlg, DigestedDataOutputStream.IMPLICIT);
       
   // the further proceeding is same as above
   
   // write in the data to be digested
   byte[] buffer = new byte[2048];
   int bytesRead;
   while ((bytesRead = dataInputStream.read(buffer)) != -1) {
     digestedData.write(buffer, 0, bytesRead);
   }
   // closing the stream calculates and writes the digest vaue and closes the underlying stream
   digestedData.close();
 
Use class DigestedDataStream to read in and parse the encoded DigestedData and verify the digest value.

See Also:
ContentInfoOutputStream, DigestedDataStream

Field Summary
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.
 
Constructor Summary
DigestedDataOutputStream(ObjectID contentType, java.io.OutputStream out, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g.
DigestedDataOutputStream(ObjectID contentType, java.io.OutputStream out, AlgorithmID digestAlgorithm, int mode, SecurityProvider securityProvider)
          Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g.
DigestedDataOutputStream(java.io.OutputStream out, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g.
 
Method Summary
 void close()
          Finishes the encoding and calculates and writes the digest value to the stream.
 void flush()
          Flushes any internal data and calls flush of the underlying stream.
 byte[] getDigest()
          Returns the message-digest computed on the content value.
 SecurityProvider getSecurityProvider()
          Gets the SecurityProvider installed for this DigestedDataOutputStream.
 int getVersion()
          Returns the version syntax number.
 boolean isPassThroughClose()
          Checks whether a call to close() will call close of the underlying output stream
 void setDigest(byte[] digest)
          Sets the message-digest value.
 void setPassThroughClose(boolean passThroughClose)
          Setting this to true will cause close() to call close of the underlying output stream.
 void setSecurityProvider(SecurityProvider securityProvider)
          Sets the SecurityProvider for this DigestedDataOutputStream.
 java.lang.String toString()
          Returns a string giving some information about this DigestedDataOutputStream object.
 java.lang.String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this DigestedDataOutputStream object.
 void write(byte[] b)
          Processes the given content data to be digested.
 void write(byte[] b, int off, int len)
          Processes the given content data to be digested.
 void write(int b)
          Processes the given content byte to be digested.
 
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
Constructor Detail

DigestedDataOutputStream

public DigestedDataOutputStream(java.io.OutputStream out,
                                AlgorithmID digestAlgorithm,
                                int mode)
                         throws CMSException
Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g. write(byte[])). The content type of the inherent content data is set to ObjectID.cms_data.

Parameters:
out - The output stream to which to write the encoded DigestedData structure.
digestAlgorithm - the digest algorithm to be used
mode - The mode. Either IMPLICIT for including the content or EXPLICIT for not including it.
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedDataOutputStream

public DigestedDataOutputStream(ObjectID contentType,
                                java.io.OutputStream out,
                                AlgorithmID digestAlgorithm,
                                int mode)
                         throws CMSException
Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g. write(byte[])).

Parameters:
contentType - the content type of the data to be digested
out - The output stream to which to write the encoded DigestedData structure.
digestAlgorithm - the digest algorithm to be used
mode - The mode. Either IMPLICIT for including the content or EXPLICIT for not including it.
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedDataOutputStream

public DigestedDataOutputStream(ObjectID contentType,
                                java.io.OutputStream out,
                                AlgorithmID digestAlgorithm,
                                int mode,
                                SecurityProvider securityProvider)
                         throws CMSException
Creates a new DigestedDataOutputStream object which later writes the complete encoded DigestedData structure to the given output stream (e.g. write(byte[])).

Parameters:
contentType - the content type of the data to be digested
out - The output stream to which to write the encoded DigestedData structure.
digestAlgorithm - the digest algorithm to be used
mode - The mode. Either IMPLICIT for including the content or EXPLICIT for not including it.
securityProvider - The optional security provider for getting the required crypto algorithm implementations.
Throws:
CMSException - if there is no implementation for the requested hash algorithm implementation for the requested hash algorithm
Method Detail

write

public void write(byte[] b,
                  int off,
                  int len)
           throws java.io.IOException
Processes the given content data to be digested. The data is hashed with the digest algorithm used by this DigestedDataOutputStream. In IMPLICIT mode the content data is encoded and written to the output stream. In EXPLICIT mode the content data is not written to the output stream (since it must not be included in the DigestedData and has to be transmitted by other means), but contributes to the hash calculation as required.

Overrides:
write in class java.io.OutputStream
Parameters:
b - The data to be digested as byte array.
off - The start offset in the data array b.
len - The number of bytes to write.
Throws:
java.io.IOException - If an I/O error occurs.

write

public void write(byte[] b)
           throws java.io.IOException
Processes the given content data to be digested. The data is hashed with the digest algorithm used by this DigestedDataOutputStream. In IMPLICIT mode the content data is encoded and written to the output stream. In EXPLICIT mode the content data is not written to the output stream (since it must not be included in the DigestedData and has to be transmitted by other means), but contributes to the hash calculation as required.

Overrides:
write in class java.io.OutputStream
Parameters:
b - The data to be digested as byte array.
Throws:
java.io.IOException - If an I/O error occurs.

write

public void write(int b)
           throws java.io.IOException
Processes the given content byte to be digested. The data is hashed with the digest algorithm used by this DigestedDataOutputStream. In IMPLICIT mode the content data is encoded and written to the output stream. In EXPLICIT mode the content data is not written to the output stream (since it must not be included in the DigestedData and has to be transmitted by other means), but contributes to the hash calculation as required.

Note that when repeatedly calling this method to write single data bytes the encoding may consist of many single-byte OCTET STRINGs. Thus it may be more appropriate to use a byte array expcting write method.

Specified by:
write in class java.io.OutputStream
Parameters:
b - The content data byte to be digested
Throws:
java.io.IOException - If an I/O error occurs.

flush

public void flush()
           throws java.io.IOException
Flushes any internal data and calls flush of the underlying stream.

Specified by:
flush in interface java.io.Flushable
Overrides:
flush in class java.io.OutputStream
Throws:
java.io.IOException - If flushing the stream fails.

close

public void close()
           throws java.io.IOException
Finishes the encoding and calculates and writes the digest value to the stream.

Specified by:
close in interface java.io.Closeable
Overrides:
close in class java.io.OutputStream
Throws:
java.io.IOException - if an I/O error occurs while writing to the stream

isPassThroughClose

public boolean isPassThroughClose()
Checks whether a call to close() will call close of the underlying output stream

Returns:
true if a call to close() will call close of the underlying output stream; false if a call to close() will not close the underlying stream.

setPassThroughClose

public void setPassThroughClose(boolean passThroughClose)
Setting this to true will cause close() to call close of the underlying output stream. If false, a call to close() will not close the underlying stream.

Parameters:
passThroughClose - true to pass through close() calls. false to not pass them through.

setSecurityProvider

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

This method allows to explicitly set a SecurityProvider for this DigestedDataOutputStream. 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 DigestedDataOutputStream object.

Parameters:
securityProvider - the SecurityProvider to be set

getSecurityProvider

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

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

getVersion

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

Returns:
the version syntax number

getDigest

public byte[] getDigest()
Returns the message-digest computed on the content value. If using this method, it has to be called after all data has been written and this DigestedDataOutputStream has been closed.

Returns:
the message-digest value

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

toString

public java.lang.String toString()
Returns a string giving some information about this DigestedDataOutputStream 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 DigestedDataOutputStream object.

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