iaik.cms
Class DigestedData

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

public class DigestedData
extends DigestedDataStream
implements Content

This class represents the non-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 (Version 1.5):

 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 contentInfo 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 DigestedData object for the content to be digested by using the DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode) constructor, additionally the transimission mode has to be specified. If the mode is set to DigestedData.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 DigestedData.EXPLICIT. However, in both cases the raw data has to be supplied when creating the DigestedData object, because it is needed for the digest computation:

 byte[] content = ...; // the raw data to be digested
 AlgorithmID digestAlg = ...;
 DigestedData digested_data = new DigestedData(content, digestAlg, DigestedData.IMPLICIT);
 
respectively
 DigestedData digested_data = new DigestedData(content, digestAlg, DigestedData.EXPLICIT);
 
In contrast to the stream-variant of the CMS DigestedData type (implemented by the DigestedDataStream class), where explicit and implicit mode have to be handled in different way when creating a DigestedData object, they have the same proceeding for this non-stream-supporting DigestedData class. In this way, after having created a DigestedData object the only remaining task is to prepare the DigestedData object for transmission by transforming it into an ASN1Object or immediately DER encoding it. The former is done by calling the toASN1Object method, the latter by using the getEncoded method:
 ASN1Object obj = digested_data.toASN1Object();
 
respectively
 byte[] encoding = digested_data.getEncoded();
 
You alternatively may use a proper writeTo method of the parent DigestedDataStream class for immediately encoding this DigestedData object to an output stream. When using writeTo in implicit mode, you additionally have the possibility of specifying a particular blockSize for forcing an indefinite constructed encoding of the inherent raw data bytes, instead of of the default definite primitive encoding, 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.

Unlike the procedure of newly creating a DigestedData object to be transmitted, even when using this non-stream implementation of the DigestedData content type, it has to be distinguished between IMPLICIT and EXPLICIT mode when 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 DigestedData object from the DigestedData ASN1Object by calling the DigestedData(ASN1Object obj) constructor. On the other side, when the raw data has been transmitted outside the DigestedData message (EXPLICIT mode), the DigestedData(byte[] content, AlgorithmID digestAlgorithm) constructor has be to used for initializing the new DigestedData 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 computing the digest on the raw data for the supplied digest algorithm. Later, during digest verification this digest value has to be compared against the hash value sent within the digest field.
All further steps are the same for implicit and explicit mode, and so the proceeding necessary for parsing a received DigestedData message and verifying the digest may be summarized as follows:

  1. If nessecary, first decode the received DER encoded mesage to obtain an ASN1Object:
         ASN1Object obj = DerCoder.decode(received_message);
         
  2. If the ASN1Object resulting from step 1 above represents an implicit DigestedData object, use the DigestedData(ASN1Object obj) constructor for creating a DigestedData object and implicitly parsing the the supplied ASN.1 structure:
         DigestedData digestedData = new DigestedData(obj);
         
    On the other hand, if the ASN1Object resulting from step 1 above represents an explicit DigestedData object, use the DigestedData(byte[] content, AlgorithmID digestAlgorithm) constructor for initializing a new DigestedData object with raw data and digest algorithm for hash computation, and subsequently explicitly perform the decoding by means of the decode method (assuming that the SHA-1 hash algorithm is used):
         AlgorithmID algIDs =  AlgorithmID.sha1;
         DigestedData digestedData = new DigestedData(raw_data, algID);
         digestedData.decode(obj);
         
  3. Now verify the digest:
         if (digestedData.verify()) {
            System.out.println("Hash ok!");
         else
            System.out.println("Message corrupted!");
         
  4. In implicit mode, get the raw data from the DigestedData object:
         byte[] data = digestedData.getContent();
         

Use the stream supporting DigestedDataStream parent class for handling structures with large amounts of data.


Field Summary
 
Fields inherited from class iaik.cms.DigestedDataStream
blockSize_, contentType_, digestAlgorithm_, encapContentInfo_, EXPLICIT, IMPLICIT, inputStream_, mode_, securityProvider_, version_
 
Constructor Summary
protected DigestedData()
          Default constructor for dynamic object creation in ContentInfo.
  DigestedData(ASN1Object obj)
          Creates a CMS DigestedData from an ASN1Object.
  DigestedData(ASN1Object obj, SecurityProvider securityProvider)
          Creates a CMS DigestedData from an ASN1Object.
  DigestedData(byte[] content, AlgorithmID digestAlgorithm)
          Creates a new DigestedData from a byte array holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.
  DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedData object from given content and and digest algorithm.
  DigestedData(byte[] content, AlgorithmID digestAlgorithm, SecurityProvider securityProvider)
          Creates a new DigestedData from a byte array holding the content that has been transmitted by other means, and the hash algorithm to be used for digesting.
  DigestedData(java.io.InputStream is)
          Creates a DigestedData object from a DER encoded DigestedData object which is read from the given input stream.
  DigestedData(java.io.InputStream is, SecurityProvider securityProvider)
          Creates a DigestedData object from a DER encoded DigestedData object which is read from the given input stream.
  DigestedData(ObjectID contentType, AlgorithmID digestAlgorithm, byte[] digest)
          Creates a new DigestedData object without content.
  DigestedData(ObjectID contentType, byte[] content, AlgorithmID digestAlgorithm, int mode)
          Creates a new DigestedData object from given content and and digest algorithm.
  DigestedData(ObjectID contentType, byte[] content, AlgorithmID digestAlgorithm, int mode, SecurityProvider securityProvider)
          Creates a new DigestedData object from given content and and digest algorithm.
 
Method Summary
 void decode(ASN1Object obj)
          Decodes the given DigestedData ASN1 object.
 void decode(java.io.InputStream is)
          Reads and decodes the encoded DigestedData from an input stream.
 byte[] getContent()
          Returns the content.
 byte[] getEncoded()
          Returns the encoding of this DigestedData in a byte array.
 java.io.InputStream getInputStream()
          Returns an InputStream from which the contents of this object can be read.
 void setContent(byte[] content)
          Sets the content to sign/verify.
protected  void setupMessageDigest(AlgorithmID digestAlgorithm, boolean parse)
          Calculates the digest.
protected  ASN1Object toASN1Object(int blockSize)
          Returns this DigestedData as ASN1Object.
 java.lang.String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this DigestedData object.
 
Methods inherited from class iaik.cms.DigestedDataStream
encodeCalled, getBlockSize, getContentType, getDigest, getDigestAlgorithm, getEncapsulatedContentType, getMode, getSecurityProvider, getVersion, notifyEOF, setBlockSize, setDigest, setInputStream, setSecurityProvider, toASN1Object, toString, verify, writeTo, writeTo
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface iaik.cms.ContentStream
getBlockSize, getContentType, setBlockSize, toASN1Object
 

Constructor Detail

DigestedData

protected DigestedData()
Default constructor for dynamic object creation in ContentInfo. Shall not be used by an application. The block size is set to -1 to enforce definite primitive encoding.


DigestedData

public DigestedData(byte[] content,
                    AlgorithmID digestAlgorithm,
                    int mode)
             throws CMSException
Creates a new DigestedData object from given content and and digest algorithm. The data to be digested is supplied as byte array. 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:
content - the data to be digested supplied from a byte array
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either Digested.IMPLICIT for including the data, or DigestedData.EXPLICIT for not including it
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedData

public DigestedData(ObjectID contentType,
                    byte[] content,
                    AlgorithmID digestAlgorithm,
                    int mode)
             throws CMSException
Creates a new DigestedData object from given content and and digest algorithm. The data to be digested is supplied as byte array. 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
content - the data to be digested supplied from a byte array
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either Digested.IMPLICIT for including the data, or DigestedData.EXPLICIT for not including it
Throws:
CMSException - if there is no implementation for the requested hash algorithm

DigestedData

public DigestedData(ObjectID contentType,
                    byte[] content,
                    AlgorithmID digestAlgorithm,
                    int mode,
                    SecurityProvider securityProvider)
             throws CMSException
Creates a new DigestedData object from given content and and digest algorithm. The data to be digested is supplied as byte array. 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
content - the data to be digested supplied from a byte array
digestAlgorithm - the message-digest algorithm to be used for creating the digest
mode - either Digested.IMPLICIT for including the data, or DigestedData.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

DigestedData

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

For instance:

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

The content must be supplied 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 result of the message-digesting process

DigestedData

public DigestedData(ASN1Object obj)
             throws CMSParsingException
Creates a CMS DigestedData from an ASN1Object. The ASN.1 DigestedData may (or may not) be wrapped into a ContentInfo.

Do not use this constructor for supplying content and hashed content value. This constructor may be used by the recipient for parsing an already exisiting DigestedData object, supplied as ASN1Object that may have been created by calling toASN1Object.

Use the DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode) constructor for supplying content and hashed content value when creating a DigestedData object.

Parameters:
obj - the CMS DigestedData as ASN1Object
Throws:
CMSParsingException - if the object can not be parsed

DigestedData

public DigestedData(ASN1Object obj,
                    SecurityProvider securityProvider)
             throws CMSParsingException
Creates a CMS DigestedData from an ASN1Object. The ASN.1 DigestedData may (or may not) be wrapped into a ContentInfo.

Do not use this constructor for supplying content and hashed content value. This constructor may be used by the recipient for parsing an already exisiting DigestedData object, supplied as ASN1Object that may have been created by calling toASN1Object.

Use the DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode) constructor for supplying content and hashed content value when creating a DigestedData object.

Parameters:
obj - the CMS DigestedData as ASN1Object
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
CMSParsingException - if the object can not be parsed

DigestedData

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

Parameters:
is - the InputStream holding the 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

DigestedData

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

Parameters:
is - the InputStream holding the 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

DigestedData

public DigestedData(byte[] content,
                    AlgorithmID digestAlgorithm)
             throws java.security.NoSuchAlgorithmException
Creates a new DigestedData from a byte array 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. In contrast to the equivalent constructor of the parent DigestedDataStream class, this constructor not only initializes the digest computation, but also already computes the digest for the given digest algorithm. Later, during digest verification these digest value have to be compared against the hash value sent in the digest field.
For subsequently performing the decoding of the received explicit DigestedData object, use the decode method:

 //initialize - and perform - digest computaion:
 DigestedData digestedData = new DigestedData(raw_data, hashAlgorithm);
 //parse the received DigestedData ASN1Object
 ASN1Object obj = DerCoder.decode(encodedDigestesData);
 digestedData.decode(obj);
 

A sender shall use the DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content value to be digested when creating a DigestedData object.

For parsing an implicit DigestedData message, use the DigestedData(ASN1Object obj) constructor.

Parameters:
content - the content transmitted by other means
digestAlgorithm - the hash algorithm used for digesting the content data
Throws:
java.security.NoSuchAlgorithmException - if the supplied hash algorithm is not supported

DigestedData

public DigestedData(byte[] content,
                    AlgorithmID digestAlgorithm,
                    SecurityProvider securityProvider)
             throws java.security.NoSuchAlgorithmException
Creates a new DigestedData from a byte array 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. In contrast to the equivalent constructor of the parent DigestedDataStream class, this constructor not only initializes the digest computation, but also already computes the digest for the given digest algorithm. Later, during digest verification these digest value have to be compared against the hash value sent in the digest field.
For subsequently performing the decoding of the received explicit DigestedData object, use the decode method:

 //initialize - and perform - digest computaion:
 DigestedData digestedData = new DigestedData(raw_data, hashAlgorithm);
 //parse the received DigestedData ASN1Object
 ASN1Object obj = DerCoder.decode(encodedDigestesData);
 digestedData.decode(obj);
 

A sender shall use the DigestedData(byte[] content, AlgorithmID digestAlgorithm, int mode) constructor for supplying the content value to be digested when creating a DigestedData object.

For parsing an implicit DigestedData message, use the DigestedData(ASN1Object obj) constructor.

Parameters:
content - the content transmitted by other means
digestAlgorithm - the hash algorithm used for digesting the content data
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
java.security.NoSuchAlgorithmException - if the supplied hash algorithm is not supported
Method Detail

setupMessageDigest

protected void setupMessageDigest(AlgorithmID digestAlgorithm,
                                  boolean parse)
                           throws java.security.NoSuchAlgorithmException
Calculates the digest.

Parameters:
digestAlgorithm - the digest algorithm to be used
parse - whether this method id called during the parsing or creation process
Throws:
java.security.NoSuchAlgorithmException - if the digestAlgorithm is not supported

decode

public void decode(ASN1Object obj)
            throws CMSParsingException
Decodes the given DigestedData ASN1 object. The ASN.1 DigestedData may (or may not) be wrapped into a ContentInfo.

Specified by:
decode in interface Content
Parameters:
obj - the ASN1Object representing an already exisiting DigestedData object
Throws:
CMSParsingException - if an error occurs when parsing the given ASN1Object

decode

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

Specified by:
decode in interface ContentStream
Overrides:
decode in class DigestedDataStream
Parameters:
is - the InputStream supplying a DER 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

getInputStream

public java.io.InputStream getInputStream()
Returns an InputStream from which the contents of this object can be read.

This method only overrides the corresponding getInputStream method of the parent DigestedDataStream class for returning the content of this DigestedData object. There should be no real necessity for using this method since the raw data bytes immediately can be obtained by the getContent method. However, in contrast to the equivalent getInputStream method of the parent DigesetdDataStream class, this method may be called arbitrarly often; it only returns a ByteArrayInputStream that is initialized with the raw content bytes.

Overrides:
getInputStream in class DigestedDataStream
Returns:
an InputStream with the contents of this DigestedData object

getContent

public byte[] getContent()
Returns the content.

Returns:
the content as byte array

setContent

public void setContent(byte[] content)
                throws CMSException
Sets 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 content received by other means
 byte[] content = ...;

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

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

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

getEncoded

public byte[] getEncoded()
                  throws CMSException
Returns the encoding of this DigestedData in a byte array. If for the inherent content structure a positive blocksize has been specified, the content is encoded as indefinite constructed octet string.

Returns:
a byte array holding the DER encoding of this DigestedData
Throws:
CMSException - if an error occurs during the encoding procedure

toASN1Object

protected ASN1Object toASN1Object(int blockSize)
                           throws CMSException
Returns this DigestedData as ASN1Object.

The ASN1Object returned by this method may be used as parameter value when creating a DigestedData object using the DigestedData(ASN1Object obj) constructor.

Overrides:
toASN1Object in class DigestedDataStream
Parameters:
blockSize - the blockSize to be used for block oriented encoding
Returns:
this DigestedData as ASN1Object.
Throws:
CMSException - if the ASN1Object could not be created

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
Overrides:
toString in class DigestedDataStream
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 5.1, (c) 2002 IAIK, (c) 2003 - 2010 SIC