iaik.pkcs.pkcs7
Class SignedDataStream

java.lang.Object
  |
  +--iaik.pkcs.pkcs7.SignedDataStream
All Implemented Interfaces:
ContentStream, iaik.pkcs.pkcs7.DigestProvider, EOFListener, EventListener
Direct Known Subclasses:
SignedAndEnvelopedDataStream, SignedData

public class SignedDataStream
extends Object
implements ContentStream, EOFListener, iaik.pkcs.pkcs7.DigestProvider

This class represents the stream-implementation of the PKCS#7 content type SignedData.

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

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

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

signedData OBJECT IDENTIFIER ::= { pkcs-7 2 }

which corresponds to the OID string "1.2.840.1.113549.1.7.2".

The PKCS#7 Cryptographic Message Standard specifies the SignedData content type for providing a syntax for building digital signatures. Content of any type may be signed by any number of signers in parallel. For each signer, a message digest is computed on the content (and any additional authenticating information) with a signer-specific message-digest algorithm. Subsequently, again for each signer, the corresponding message digest from the previous step is encrypted with the particular signer´s private key and - together with some signer-specific information - collected into a SignerInfo value. Finally all created SignerInfo values are collected together with the content for forming a SignedData structure.

This class implements the SignedData structure resulting from the last step described above. The SignedData type is defined as ASN.1 SEQUENCE type containing the following components (see PKCS#7 specification, Version 1.5; notice that the ASN.1 module printed below not fully agrees with the SignedData definition of Version 1.5, since the certificates field is interpreted as SET OF pure X.509 certificates, whereas Version 1.5 also alows PKCS#6 extended certificates!):

 SignedData ::= SEQUENCE {
   version           Version,
   digestAlgorithms  DigestAlgorithmIdentifiers,
   contentInfo       ContentInfo,
   certificates      [0] IMPLICIT Certificates OPTIONAL,
   crls              [1] IMPLICIT CertificateRevocationLists OPTIONAL,
   signerInfos       SignerInfos }
 
DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
Certificates ::= SET OF Certificate -- X.509
CertificateRevocationLists ::= SET OF CertificateRevocationList
SignerInfos ::= SET OF SignerInfo

The digestAlgorithms field contains the object identifiers of the message digest algorithms used by the several signers for digesting the content that is supplied in the contentInfo field. The optional certificates field shall contain certificate chains for all the signers of the signerInfos field. The optional crls field may supply information about the revocation status of the certificates specified in the certificates field. And finally, the signerInfos field collects per-signer information for all parciticipated signers including the encrypted digests of the content (i.e. the signer-specific digital signatures of the content).

If there are no signers on the content, the signed-data content type may be used for disseminating certificates and certificate-revocation lists.

Verifying some received signature(s) is done by decrytping the encrypted message digests for each signer with the signer´s public key and comparing the results with idependently computed message digests on the original content.

For more information consult the RSA PKCS#7 specification.

The SignedData version implemented by this class complies with the SignedData structure as used by the S/MIME protocol. In this way, the digest is calculated on only the content octets of the DER encoding of the content field of the inherent ContentInfo structure. At this point it is important to note that currently IAIK-JCE only supports SignedData structures to be used for signing content values of the PKCS#7 Data content type!


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

 InputSrteam[] data_stream = ...; // the raw data supplying input stream
 SignedDataStream signed_data = new SignedDataStream(data_stream, SignedDataStream.IMPLICIT);
 
respectively
 SignedDataStream signed_data_stream = new SignedDataStream(data_stream, SignedDataStream.EXPLICIT);
 
In contrast to the non-stream-variant of the PKCS#7 SignedData type (implemented by the SignedData class), where explicit and implicit mode can be handled in the same way when creating a SignedData object, they require a different proceeding for the stream-supporting SignedDataStream class. In this way, the steps for creating a SignedDataStream object and preparing it for transmission can be summarized in the following way (to simplify matters, we will assume not to include certificate revocation lists):
  1. Create a new SignedDataStream object thereby supplying the raw data to be signed as input stream and specifying the transmission mode to be used (either SignedDataStream.IMPLICIT or SignedDataStream.EXPLICIT):
         InputStream data_stream = ...;
         int mode = ...;
         SignedDataStream signed_data = new SignedDataStream(data_stream, mode);
         
  2. Set the certificates of all the signers by calling the setCertificates method. The certificates are supplied as array of X509Certificates and shall contain chains from a known top-level CA to all the signers in the SignerInfo field:
         signed_data.setCertificates(certificates);
         
  3. For each participated signer, create a SignerInfo object, optionally supply it with attributes, and add it to the SignedDataStream structure by calling the addSignerInfo method:
         SignerInfo signer1 = ...;
         signed_data.addSignerInfo(signer1);
         SignerInfo signer2 = ...;
         signed_data.addSignerInfo(signer2);
          ...
         
    You alternatively may collectively add all signers by utilizing the setSignerInfos method.
    When actually adding a SignerInfo the digest computation is initialized by wrapping a digest stream for the signer´s particular digest algorithm around the data carrying input stream.

  4. If the mode chosen in step 1 when creating the SignedDataStream object has been SignedDataStream.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 SignedData message, the stream has to be read before actually performing the encoding. When reading the stream, the data is piped to all the signer specific digest streams for updating the hash computation.
         if (mode == SignedDataStream.EXPLICIT) {
           InputStream data_is = signed_data.getInputStream();
           byte[] buf = new byte[1024];
           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.

  5. Use a proper writeTo method for BER encoding the the SignedDataStream object and writing it to an output stream. You optionally may specify a particular block size for splitting the data encoding:
         int blockSize = ...;
         signed_data.writeTo(output_stream, blockSize);
         
    respectively
         signed_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 SignedData 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 SignedData implementation. When a positve block size is specified for encoding the SignedData 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. The indefinte constrcuted encoding scheme also may be preferable when intending to be compatible to the encoding practice of some particular application (for instance some versions of Netscape Navigator).

Again, it has to be distinguished between IMPLICIT and EXPLICIT mode when using the SignedDataStream implementation for parsing a received SignedData message. When operating in IMPLICIT mode, the raw data is included in the received SignedData object, and so the parsing immediately may be performed when creating a SignedDataStream object from the DER encoded SignedData object by calling the SignedDataStream(InputStream is) constructor. On the other side, when the raw data has been transmitted outside the SignedData message (EXPLICIT mode), the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor has to be used for initializing the new SignedDataStream object with raw data and hash algorithms 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 digest algorithms of all participated signers. Later, during signature verification the digest value computaion is finished and the results are compared against the hash values resulting from decrypting the encrypted digests with the signer´s public keys.
The individual steps necessary for parsing a received SignedData message and verifying the signatures may be summarized as follows:

  1. If the InputStream supplies the BER encoding of an implicit SignedData object, use the SignedDataStream(InputStream is) constructor for creating a SignedDataStream object and implicitly performing the decoding:
         SignedDataStream signedData = new SignedDataStream(encoded_stream);
         
    On the other hand, if the BER encoding represents an explicit SignedData object, use the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor for initializing a new SignedDataStream object with raw data and digest algorithms for hash computation (assuming that two hash algorithms are used: SHA and MD5):
         AlgorithmID[] algIDs = { AlgorithmID.sha1, AlgorithmID.md5 };
         SignedDataStream signedData = new SignedDataStream(data_is, algIDs);
         
  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 all participated digest algorithms, either implicitly parsed from the supplied SignedData object, or explicitly supplied as an array of hash algorithm IDs. When now reading the stream, the data is piped through the digest streams for updating the hash computation:
         InputStream dataIs = signedData.getInputStream();
         byte[] buf = new byte[1024];
         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:
         signedData.decode(encoded_stream);
         
  4. Get the SignerInfos from the SignedData object and perform the signature verification:
         // get the signer infos
         SignerInfo[] signer_infos = signed_data.getSignerInfos();
         // verify the signatures
         for (int i=0; i < signer_infos.length; i++) {
           try {
              // verify the signature for SignerInfo at index i
              X509Certificate signer_cert = signed_data.verify(i);
              // if the signature is OK the certificate of the signer is returned
              System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
           } catch (SignatureException ex) {
              // if the signature is not OK a SignatureException is thrown
              System.out.println("Signature ERROR from signer: "+signed_data.getCertificate(signer_infos[i].getIssuerAndSerialNumber()).getSubjectDN());
           }
         }
         

Version:
File Revision 47
See Also:
ContentStream, ContentInfoStream, SignerInfo, SignedData

Field Summary
protected  int block_size
          The block size for block oriented stream encoding.
protected  X509Certificate[] certificates
          Repository for the signer certificates.
protected  ContentInfoStream content_info
          The inherent ContentInfo.
protected  ObjectID content_type
          The content type.
protected  X509CRL[] crls
          Repository for any included CRLs.
static int EXPLICIT
          Denotes a mode where the signed message is not transported within the Signature
static int IMPLICIT
          Denotes a mode where the signed message is included in the Signature
protected  InputStream input_stream
          An InputStream holding the data.
protected  int mode
          The mode specifying if the signed message is included in the Signature (IMPLICIT), or if is not transported within the Signature (EXPLICIT).
protected  Vector signer_infos
          Repository for the SignerInfos.
protected  DerInputStream this_object
          An InputStream from which a DER encoded SignedData object is read.
protected  int version
          The version number, currently 1.
 
Constructor Summary
protected SignedDataStream()
          Default constructor for dynamic object creation in ContentInfo.
  SignedDataStream(InputStream is)
          Creates a new SignedDataStream where the DER encoded data is read from the given InputStream.
  SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms)
          Creates a new SignedDataStream from an InputStream holding the content that has been transmitted by other means, and an array specifying the hash algorithms to be used for digesting.
  SignedDataStream(InputStream data_is, int mode)
          Creates a SignedDataStream object from an input stream supplying the data to be signed.
  SignedDataStream(ObjectID contentType)
          Creates a new SignedDataStream object without any content.
 
Method Summary
 void addSignerInfo(SignerInfo signerInfo)
          Adds a SignerInfo object to this SignedData.
 void decode(InputStream is)
          Reads and decodes the SignedDataStream from a DerInputStream.
 int getBlockSize()
          Gets the block size defining the length of each definite primitive encoded octet string component.
 X509Certificate getCertificate(IssuerAndSerialNumber issuer)
          Tries to find the certificate specified by an IssuerAndSerialNumber.
 X509Certificate[] getCertificates()
          Returns the certificates of the signers.
 ObjectID getContentType()
          Returns the content type this class implements.
 X509CRL[] getCRLs()
          Returns all the cerificate-revocation lists included in this SignedData object.
 AlgorithmID[] getDigestAlgorithms()
          Returns a collection of message-digest algorithm identifiers.
 InputStream getInputStream()
          Returns an InputStream from where the signed content can be read.
 byte[] getMessageDigest(AlgorithmID digestAlgorithm)
          Returns the message digest calculated for a specific algorithm.
 int getMode()
          Returns the mode of this SignedData.
 byte[] getSignedDigest(int signerInfoIndex)
          Returns the message digest included in the authenticated attributes.
 SignerInfo[] getSignerInfos()
          Returns all the signer infos included in this SignedData object.
 int getVersion()
          Returns the syntax version 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 setCertificates(X509Certificate[] certificates)
          Sets the certificates of the several signers.
 void setCRLs(X509CRL[] crls)
          Sets a set of cerificate-revocation lists.
 void setInputStream(InputStream is)
          Sets the InputStream which holds the content to sign.
 void setMessageDigest(AlgorithmID digestAlgorithm, byte[] digest)
          This method can be used to set an externally calculated MessageDigest.
 void setSignerInfos(SignerInfo[] signerInfos)
          Sets a collection of per-signer information.
 ASN1Object toASN1Object()
          Returns this SignedDataStream as ASN1Object.
protected  ASN1Object toASN1Object(int blockSize)
          Returns this SignedData as ASN1Object where a constructed OCTET STRING is used for encoding the content.
 String toString()
          Returns a string giving some information about this SignedDataStream object.
 String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this SignedDataStream object.
 X509Certificate verify(int signerInfoIndex)
          Verifies the signature that has been created by the signerInfoIndex´th signer.
 void verify(PublicKey publicKey, int signerInfoIndex)
          Uses the provided public key for verifying the signature that has been created by the signerInfoIndex´th signer.
 SignerInfo verify(X509Certificate signerCertificate)
          Uses the provided signer certificate for verifying the signature that has been created by the signer being owner of the certificate.
 void writeTo(OutputStream os)
          DER encodes and writes this object to the supplied output stream.
 void writeTo(OutputStream os, int blockSize)
          Writes this object to the supplied output stream where a constructed OCTET STRING is used for encoding the content.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

IMPLICIT

public static final int IMPLICIT
Denotes a mode where the signed message is included in the Signature

EXPLICIT

public static final int EXPLICIT
Denotes a mode where the signed message is not transported within the Signature

version

protected int version
The version number, currently 1.

content_type

protected ObjectID content_type
The content type.

content_info

protected ContentInfoStream content_info
The inherent ContentInfo.

certificates

protected X509Certificate[] certificates
Repository for the signer certificates.

crls

protected X509CRL[] crls
Repository for any included CRLs.

signer_infos

protected Vector signer_infos
Repository for the SignerInfos.

this_object

protected DerInputStream this_object
An InputStream from which a DER encoded SignedData object is read.

input_stream

protected InputStream input_stream
An InputStream holding the data.

mode

protected int mode
The mode specifying if the signed message is included in the Signature (IMPLICIT), or if is not transported within the Signature (EXPLICIT).

block_size

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

SignedDataStream

protected SignedDataStream()
Default constructor for dynamic object creation in ContentInfo. Shall not be used by an application for creating a SignedDataStream object. The block size is set to 2048.

SignedDataStream

public SignedDataStream(ObjectID contentType)
Creates a new SignedDataStream object without any content. The content value to be signed has to be of the given content type and has to be supplied by other means.
Parameters:
contentType - the contentType of the data

SignedDataStream

public SignedDataStream(InputStream data_is,
                        int mode)
Creates a SignedDataStream object from an input stream supplying the data to be signed. The given mode specifies the way the raw data is transmitted. If the mode is SignedDataStream.IMPLICIT, the raw data is included in the SignedData message to be transmitted. If the mode is SignedDataStream.EXPLICIT, the raw data is not included in the SignedData object.
Parameters:
data_is - a stream holding the data to sign
IMPLICIT - if the message shall be included in the DER encoding, EXPLICIT otherwise

SignedDataStream

public SignedDataStream(InputStream is)
                 throws PKCSParsingException,
                        IOException
Creates a new SignedDataStream where the DER encoded data is read from the given InputStream.

Do not use this constructor for supplying the content data to be signed. This constructor may be used by the recipient for parsing an already exisiting SignedDataStream object, supplied as DER encoding from an input stream, and may have been created by one of the writeTo methods.

Use the SignedDataStream(InputStream data_is, int mode) constructor for supplying the content data to be signed when creating a SignedDataStream object.

This constructor only shall be used for decoding a SignedData object with included raw data (implicit mode).
To initialize a SignedDataStream object for parsing an explicit SignedData message where the raw data is not included, use the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor, and perform the decoding explicitly by calling the decode method.

Parameters:
is - the InputStream holding a DER encoded PKCS#7 SignedData object
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object

SignedDataStream

public SignedDataStream(InputStream data_is,
                        AlgorithmID[] hashAlgorithms)
                 throws IOException
Creates a new SignedDataStream from an InputStream holding the content that has been transmitted by other means, and an array specifying the hash algorithms to be used for digesting.

Do not use this constructor for supplying the content value to be signed. This constructor may be used by the recipient for initializing the digest computation for an already existing explicit SignedDataStream message where the raw data is not included. The initialization is done by wrapping a digest stream around the supplied raw data stream for any specified hash algorithm. Subsequently the hash values will be updated when reading the stream thereby piping the data through the digest streams. Later, during signature verification the digest computaion is finished and the results are compared with the hash values derived from decrypting the encrypted digests with the signer´s public keys.
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:
 SignedDataStream signedData = new SignedDataStream(data_is, hashAlgorithms);
 //read the stream thereby updating the hash values:
 InputStream dataIs = signed_data.getInputStream();
 byte[] buf = new byte[1024];
 int r;
 while ((r = dataIs.read(buf)) > 0) {
   // do something useful
 }
 // explicitly perform the decoding
 signedData.decode(encoded_stream);
 

A sender shall use the SignedDataStream(InputStream data_is, int mode) constructor for supplying the content to be signed when creating a SignedDataStream object.

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

Parameters:
data_is - the InputStream supplying the raw data which has been transmitted by other means
hashAlgorithms - the hash algorithms used by the participated signers for digesting the content data
Throws:
IOException - if there is no implementation for the specified hash algorithm
Method Detail

decode

public void decode(InputStream is)
            throws IOException,
                   PKCSParsingException
Reads and decodes the SignedDataStream from a DerInputStream. If the supplied InputStream actually is not an instance of DerInputStream, internally a DerInputStream is created before parsing the data.

This method implicitly is called from inside the corresponding constructor for decoding an received implicit SignedDataStream object where the raw data is included. This method has to be explicitly called for decoding a received explicit SignedDataStream object where the raw data is not included. Before calling this method for decoding an explicit message, a new SignedDataStream object has to be created by means of the SignedDataStream(InputStream data_is, AlgorithmID[] hashAlgorithms) constructor for initializing it for hash computation, and the data has to be read from the stream for upadating the hash values:

 // initialize for hash computation:
 SignedDataStream signedData = new SignedDataStream(data_is, hashAlgorithms);
 //read the stream thereby updating the hash values:
 InputStream dataIs = signed_data.getInputStream();
 byte[] buf = new byte[1024];
 int r;
 while ((r = dataIs.read(buf)) > 0) {
   // do something useful
 }
 // explicitly perform the decoding
 signedData.decode(encoded_stream);
 
Specified by:
decode in interface ContentStream
Parameters:
is - the InputStream holding a DER encoded PKCS#7 SignedData object
Throws:
IOException - if an I/O error occurs during reading from the InputStream
PKCSParsingException - if an error occurs while parsing the object

notifyEOF

public void notifyEOF()
               throws IOException
This method implements the EOFListener interface for performing the final decoding. Since the certificates, crls, and signerInfos fields are located at the end of a SignedData structure, they only can be accessed after reading the data stream. For that reason, when starting the parsing of an implicit SignedData message only version, digestAlgorithms, and ContentInfo fields can be parsed before reading the data. Since the data is supplied from an input stream, a iaik.utils.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 remaining certificates, crls and signerInfos fields.
For any application it is strongly recommended recommended not to explicitly call this method. This method only is qualified as public method since it implements the iaik.utils.EOFListener interface.
Specified by:
notifyEOF in interface EOFListener
Throws:
IOException - if an error occurs while parsing the stream
See Also:
EOFListener, NotifyEOFInputStream

getMode

public int getMode()
Returns the mode of this SignedData.
Returns:
IMPLICIT or EXPLICIT

getMessageDigest

public byte[] getMessageDigest(AlgorithmID digestAlgorithm)
                        throws NoSuchAlgorithmException
Returns the message digest calculated for a specific algorithm. This method implements the DigestProvider interface, and therefore has to be qualified as public method. However, there should be no necessity for an application to utilize this method. This method only is called from inside the SignerInfo class for obtaining the digest calculated on the content for the specified hash algorithm.

It is strongly recommended not to explicitly call this method, since it actually finshes the digest computation for all hash values resulting from piping the data through the digest streams. This only has to be performed once and is done from inside the SignerInfo class!

Specified by:
getMessageDigest in interface iaik.pkcs.pkcs7.DigestProvider
Parameters:
digestAlgorithm - the hash algorithm to be used for digest computation
Returns:
the message digest calculated on the content for the given hash algorithm
Throws:
NoSuchAlgorithmException - if there is no message digest for the specified algorithm

setMessageDigest

public void setMessageDigest(AlgorithmID digestAlgorithm,
                             byte[] digest)
                      throws NoSuchAlgorithmException
This method can be used to set an externally calculated MessageDigest. The new message digest for the specified algorithm is now used for creating the SignerInfos.
Parameters:
digestAlgorithm - the hash algorithm for which the digest shall be set
digest - the new value for the messsage digest
Throws:
NoSuchAlgorithmException - if there is no message digest for the specified algorithm

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 SignedData into a ContentInfo.
Specified by:
setBlockSize in interface ContentStream
Parameters:
blockSize - for defining the encoding scheme and setting the octet string component length, if positive
See Also:
OCTET_STRING

getBlockSize

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

setInputStream

public void setInputStream(InputStream is)
Sets the InputStream which holds the content to sign. This method could be useful for writing this object several times.
Parameters:
is - InputSteam holding the content to sign

getInputStream

public InputStream getInputStream()
Returns an InputStream from where the signed content can be read.
Returns:
an InputSteam holding the signed content

getContentType

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

setCertificates

public void setCertificates(X509Certificate[] certificates)
Sets the certificates of the several signers.

It is intended that the set be sufficient to contain chains from a recognized "root" to all of the signers in the signerInfo field.

Parameters:
certificates - the certificates of the signers as array of X509Certificate

setCRLs

public void setCRLs(X509CRL[] crls)
Sets a set of cerificate-revocation lists.

The given CRLs supply information about the revocation status of the certificates specified in the certificates field.

Parameters:
crls - a set of cerificate-revocation lists as array of X509CRLs

setSignerInfos

public void setSignerInfos(SignerInfo[] signerInfos)
                    throws NoSuchAlgorithmException
Sets a collection of per-signer information.

There may be any number of elements in the collection, including zero.

Parameters:
signerInfos - a collection of per-signer information
Throws:
NoSuchAlgorithmException - if there is no implementation for the message digest algorithm specified in one signerInfo
See Also:
SignerInfo

addSignerInfo

public void addSignerInfo(SignerInfo signerInfo)
                   throws NoSuchAlgorithmException
Adds a SignerInfo object to this SignedData.

This method not only adds the given SignerInfo, but also initializes the hash computation by wrapping a digest stream for the signer´s hash algortihm around the data carrying input stream.

Parameters:
signerInfo - the SignerInfo to add
Throws:
NoSuchAlgorithmException - if there is no implementation for the message digest algorithm specified in the signerInfo
See Also:
SignerInfo

getVersion

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

getDigestAlgorithms

public AlgorithmID[] getDigestAlgorithms()
Returns a collection of message-digest algorithm identifiers.

There may be any number of elements in the collection, including zero. The returned OIDs identify the digest algorithms used by the several signers.

Returns:
the message-digest AlgorithmIDs

getCertificates

public X509Certificate[] getCertificates()
Returns the certificates of the signers.
Returns:
the certificates of the signers, or null if no certificates are included

verify

public void verify(PublicKey publicKey,
                   int signerInfoIndex)
            throws SignatureException
Uses the provided public key for verifying the signature that has been created by the signerInfoIndex´th signer.

Note that this method does not perform any certificate verifaction.

Parameters:
signerInfoIndex - the index into the SignerInfos array for identifying the SignerInfo belonging to the signer whose signature has to be verified
publicKey - the public key of the signer to verify the message
Throws:
SignatureException - if the signature turns out to be incorrect

verify

public X509Certificate verify(int signerInfoIndex)
                       throws SignatureException
Verifies the signature that has been created by the signerInfoIndex´th signer.

The signature is verified by using the specified signer´s public key, which is get from the signer´s certificate, derived from the certificates field.

Verifying the signatures of all the signer´s included into some specific SignedData object may be done by "looping" through all the included SignerInfos, e.g.:

 SignerInfo[] signer_infos = signed_data.getSignerInfos();
 for (int i=0; i<signer_infos.length; i++) {
     try {
       // verify the signed data using the SignerInfo at index i
       X509Certificate signer_cert = signed_data.verify(i);
       // if the signature is OK the certificate of the signer is returned
       System.out.println("Signature OK from signer: "+signer_cert.getSubjectDN());
     } catch (SignatureException ex) {
       // if the signature is not OK a SignatureException is thrown
       System.out.println("Signature ERROR from signer: "
                           + signed_data.getCertificate(signer_infos[i].getIssuerAndSerialNumber()).getSubjectDN());
     }
 }
 

Note that this method does not perform any certificate verifaction.

Parameters:
signerInfoIndex - the index into the SignerInfos array for identifying the SignerInfo belonging to the signer whose signature has to be verified
Returns:
the certificate of the signer, if its signature turns out to be correct; otherwise a SignaturException is thrown
Throws:
SignatureException - if the signature turns out to be incorrect

verify

public SignerInfo verify(X509Certificate signerCertificate)
                  throws SignatureException
Uses the provided signer certificate for verifying the signature that has been created by the signer being owner of the certificate. This method may be used for verifying the signature of a signer in situations where there are no certificates sent with the SignedData object. Of course, it also may be used when the certificate is not empty. However, take in mind that you should not step through the entries of the certificates field for calling verify(cert) for any certificate presented there since there also may (shall) be included issuer certificates and certificate chains leading to some trusted root.

Note that this method does not perform any certificate verifaction.

Parameters:
signerCertificate - the certificate of the signer whose signature should be verified
Returns:
the signerInfo belonging to the signer being owner of the given certificate
Throws:
SignatureException - if the signature turns out to be incorrect or there is no signer with the given certificate

getSignedDigest

public byte[] getSignedDigest(int signerInfoIndex)
                       throws PKCSException
Returns the message digest included in the authenticated attributes. If the signed content is not included in the SignedData ASN.1 object this method can be used to get to message digest of the signed content.
Parameters:
signerInfoIndex - the index into the SignerInfos array for identifying the SignerInfo belonging to the signer whose message digest shall be returned

getCertificate

public X509Certificate getCertificate(IssuerAndSerialNumber issuer)
                               throws PKCSException
Tries to find the certificate specified by an IssuerAndSerialNumber.
Parameters:
issuer - the IssuerAndSerialNumber identifying the certificate to search for
Returns:
the X509Certificate belonging to the given IssuerAndSerialNumber, if detected; otherwise a PKCSException is thrown
Throws:
PKCSException - if the requested certificate cannot be found

getCRLs

public X509CRL[] getCRLs()
Returns all the cerificate-revocation lists included in this SignedData object.
Returns:
an array containing the cerificate-revocation lists included into this SignedData object, or null if there are no CRLs included
See Also:
setCRLs(iaik.x509.X509CRL[])

getSignerInfos

public SignerInfo[] getSignerInfos()
Returns all the signer infos included in this SignedData object.
Returns:
an array containing all the SignerInfo objects included into this SignedData, or null if there are no signers specified

toASN1Object

public ASN1Object toASN1Object()
                        throws PKCSException
Returns this SignedDataStream as ASN1Object. Creates an ASN1 SEQUENCE object supplied with all the component values as defined in the PKCS#7 Cryptographic Message Standard specification.
Specified by:
toASN1Object in interface ContentStream
Returns:
this SignedDataStream as ASN1Object
Throws:
PKCSException - if the ASN1Object could not be created

toASN1Object

protected ASN1Object toASN1Object(int blockSize)
                           throws PKCSException
Returns this SignedData 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:
PKCSException - if the ASN1Object could not be created

writeTo

public void writeTo(OutputStream os)
             throws IOException
DER encodes and writes this object to the supplied output stream. In implicit mode, whole the inherent data is encoded as one single primitive definite octet string:
 0x04 <length> <data>
 
Parameters:
os - the output stream to which this SignedDataStream shall be encoded
Throws:
IOException - if an error occurs when writing to the stream

writeTo

public void writeTo(OutputStream os,
                    int blockSize)
             throws IOException
Writes this object to the supplied output stream where a constructed OCTET STRING is used for encoding the content. If 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 SignedData shall be written
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Throws:
IOException - if an error occurs during writing the object

toString

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

toString

public String toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this SignedDataStream object.
Specified by:
toString in interface ContentStream
Parameters:
detailed - - whether or not to give detailed information
Returns:
the string representation

This Javadoc may contain text parts from Internet Standard specifications (RFC 2459, 3280, 3039, 2560, 1521, 821, 822, 2253, 1319, 1321, ,2630, 2631, 2268, 3058, 2984, 2104, 2144, 2040, 2311, 2279, see copyright note) and RSA Data Security Public-Key Cryptography Standards (PKCS#1,3,5,7,8,9,10,12, see copyright note).

IAIK-JCE 3.1 with IAIK-JCE CC Core 3.1, (c) 1997-2004 IAIK