iaik.smime.ess.utils
Class SenderAndReceiptContentDigest

java.lang.Object
  extended by iaik.smime.ess.utils.SenderAndReceiptContentDigest

public class SenderAndReceiptContentDigest
extends java.lang.Object

An utility class for keeping sender signature message digest and receipt content message digest values for SignedReceipt validation.

When receiving a signed Receipt on a response to a ReceiptRequest, the sender may have to validate that the SignedData the recipient has received actually has contained the content and attributes that have been signed by the sender, and that the SignedData the receipient has received actually has been the SignedData sent by the sender. The first validation step may be done by comparing the message digest signature value that has been calculated by the sender with the value of the MsgSigDigest attribute of the signed receipt. The second validation step may be done by comparing an independently by the sender calculated hash over the receipt content with the value of the MessageDigest attribute of the signed receipt. Precondition for this validation is that the sender, when creating its SignedData-with-ReceiptRequest (calculates and) keeps the required message digest values. This class provides an utility for collecting both digest values into one SenderAndReceiptContentDigest object and putting this object into a repository from where it may be fetched when later required for signed receipt validation. The search key for the repository is the Receipt that links the SenderAndReceiptContentDigest object to the SignerInfo of the original SignedData object.
In an typical application a sender will add a ReceiptRequest to its signed content to indicate the recipient to send a signed receipt in reply to the original message:

 boolean implicit = true;
 // create a SignedContent for the data to be signed
 SignedContent sc = new SignedContent(implicit, SignedContent.SIGNED_DATA);
 // set the data to be signed
 sc.setDataHandler(dataHandler);
 // add signer certificates
 sc.setCertificates(signerCertificates);
 // create a set of standard attributes
 Attribute[] attributes = SMimeUtil.createStandardAttributes(new IssuerAndSerialNumber(encryptionCertOfSigner), true);
 // add a ReceiptRequest attribute to request a receipt to be sent back to the sender
 int size = attributes.length;
 Attribute[] signedAttributes = new Attribute[size + 1];
 System.arraycopy(attributes, 0, signedAttributes, 0, size);
 signedAttributes[size] = new Attribute(createReceiptRequest(signerCertificate.getPublicKey(), from));
 // add signer information including the signed attributes
 sc.addSigner(signerPrivateKey, signerCertificate, AlgorithmID.sha1, AlgorithmID.rsaEncryption, signedAttributes);
 // create and send a MimeMessage for the signed content   
 msg.setContent(sc, sc.getContentType());
 sc.setHeaders(msg);
 Transport.send(msg);
 
Since digest and signature values are not calculated before writing/sending the message, the required validation values shall be kept only after sending the message:
 // get the SignerInfo of the sender
 SignerInfo originatorSignerInfo = signedContent.getSignerInfos()[0];
 // get/calculate and store the validation digest values 
 SenderAndReceiptContentDigest.storeEntry(new SenderAndReceiptContentDigest(originatorSignerInfo));
 
Later, when receiving the signed reeipt content the original sender may validate the MsgSigDigest and MessageDigest values against the kept digest values (according to section 2.6 (clause 3. to 6.) of RFC 2634):
 // get the receipt content from the message received
 ReceiptContent receiptContent = (ReceiptContent)receiptMsg.getContent();
 // dump receipt information   
 Receipt receipt = (Receipt)receiptContent.getContent();
 System.out.println("Receipt received:");
 System.out.println(receipt);
 // verify the signature of the receipt signer  
 X509Certificate receiptSigner = null;
 try {
   receiptSigner = receiptContent.verify();
   System.out.println("This receipt content is signed from: "+receiptSigner.getSubjectDN());
 } catch (SignatureException ex) {
   System.out.println("Signature verification error!");
 }
 // validate the message digest values   
 try {
   SenderAndReceiptContentDigest.validateReceiptContent(receiptContent);
 } catch (ESSException ex) {
  System.out.println(ex.toString());   
 }    
 System.out.println("ReceiptContent successful validated!");
 

See Also:
ReceiptRequest, Receipt, ReceiptContent, SignerInfo, SignedContent

Field Summary
protected static java.util.Hashtable digestStore_
          Repository for keeping sender message signature digest values and receipt content digest values for later Signed Receipt validation.
protected  Receipt receipt_
          The Receipt used to map this SenderAndReceiptContentDigest to some SignerInfo.
protected  byte[] receiptContentDigest_
          The message digest value of the Receipt content.
protected  byte[] senderMessageDigest_
          The message signature digest value used by the sender to generate the original signedData signerInfo signature value.
 
Constructor Summary
SenderAndReceiptContentDigest(ASN1Object obj)
          Creates a SenderAndReceiptContentDigest from an ASN.1 object.
SenderAndReceiptContentDigest(java.io.InputStream is)
          Creates a SenderAndReceiptContentDigest from an input stream supplying the BER encoded SenderAndReceiptContentDigest.
SenderAndReceiptContentDigest(Receipt receipt, byte[] senderMessageDigest, byte[] receiptContentDigest)
          Creates SenderAndReceiptContentDigest from Receipt, sender message digest value and receipt content digest value.
SenderAndReceiptContentDigest(SignerInfo originatorSignerInfo)
          Creates SenderAndReceiptContentDigest from the given original (sender) SignerInfo.
SenderAndReceiptContentDigest(SignerInfo originatorSignerInfo, SecurityProvider securityProvider, boolean sortAttributes)
          Creates SenderAndReceiptContentDigest from the given original (sender) SignerInfo.
 
Method Summary
static void clearDigestStore()
          Clears the digest store.
 void decode(ASN1Object obj)
          Decodes the given ASN.1 SenderAndReceiptContentDigest object.
 void decode(java.io.InputStream is)
          Reads and decodes a BER encoded SenderAndReceiptContentDigest from the given input stream.
static java.util.Enumeration getAllEntries()
          Returns an Enumeration of all entries in the digest store.
static SenderAndReceiptContentDigest getEntry(Receipt receipt)
          Gets the SenderAndReceiptContentDigest with the given Receipt from the digest store.
 Receipt getReceipt()
          Returns the receipt.
 byte[] getReceiptContentDigest()
          Returns the message digest value of the Receipt content
 byte[] getSenderMessageDigest()
          Returns the message signature digest value used by the sender to generate the original signedData signerInfo signature value.
static void initDigestStore(java.io.InputStream is)
          Initializes the digest store from the given stream.
static SenderAndReceiptContentDigest removeEntry(Receipt receipt)
          Removes the SenderAndReceiptContentDigest with the given Receipt from the digest store.
static SenderAndReceiptContentDigest removeEntry(SenderAndReceiptContentDigest senderAndReceiptContentDigest)
          Removes the given senderAndReceiptContentDigest from the digest store.
static SenderAndReceiptContentDigest storeEntry(SenderAndReceiptContentDigest senderAndReceiptContentDigest)
          Keep the given senderAndReceiptContentDigest for later Signed Receipt validation.
 ASN1Object toASN1Object()
          Returns this SenderAndReceiptContentDigest as ASN1Object.
 java.lang.String toString()
          Returns a string representation of this SenderAndReceiptContentDigest.
 void validate(ReceiptContent receiptContent)
          Validates the Signed Receipt according to section 2.6 (clause 3. to 6.) of RFC 2634.
static SenderAndReceiptContentDigest validateReceiptContent(ReceiptContent receiptContent)
          Validates the Signed Receipt according to section 2.6 (clause 3. to 6.) of RFC 2634.
static void writeDigestStore(java.io.OutputStream os)
          Writes the digest store contents to the given output stream.
 void writeTo(java.io.OutputStream os)
          Writes this ESS SenderAndReceiptContentDigest object BER encoded to the given output stream.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

digestStore_

protected static java.util.Hashtable digestStore_
Repository for keeping sender message signature digest values and receipt content digest values for later Signed Receipt validation.


receipt_

protected Receipt receipt_
The Receipt used to map this SenderAndReceiptContentDigest to some SignerInfo.


senderMessageDigest_

protected byte[] senderMessageDigest_
The message signature digest value used by the sender to generate the original signedData signerInfo signature value.


receiptContentDigest_

protected byte[] receiptContentDigest_
The message digest value of the Receipt content.

Constructor Detail

SenderAndReceiptContentDigest

public SenderAndReceiptContentDigest(Receipt receipt,
                                     byte[] senderMessageDigest,
                                     byte[] receiptContentDigest)
Creates SenderAndReceiptContentDigest from Receipt, sender message digest value and receipt content digest value. The receipt may be used to associate the message digest values with the original SignerInfo of the sender.

Parameters:
receipt - the receipt to link to the SignedData SignerInfo
senderMessageDigest - the message signature digest value used by the sender to generate the original signedData signerInfo signature value
receiptContentDigest - the message digest value of the Receipt content

SenderAndReceiptContentDigest

public SenderAndReceiptContentDigest(SignerInfo originatorSignerInfo)
                              throws ESSException
Creates SenderAndReceiptContentDigest from the given original (sender) SignerInfo.

The required receipt, sender message signature digest value and receipt content digest value are calculated/obtained from the SignerInfo, if available. If not available, an ESSException is thrown. Since we assume that this constructor will be used on the sender side (for keeping the sender message signature digest value and receipt content digest value for validation when later receiving the signed receipt) the signed attributes are sorted when creating the SET OF encoding for calculation of the MsgSigDigest value.

Parameters:
originatorSignerInfo - the signerInfo (of the original sender) from which to get required receipt and digest values
Throws:
ESSException - if the given SignerInfo cannot supply receipt or digest values as required

SenderAndReceiptContentDigest

public SenderAndReceiptContentDigest(SignerInfo originatorSignerInfo,
                                     SecurityProvider securityProvider,
                                     boolean sortAttributes)
                              throws ESSException
Creates SenderAndReceiptContentDigest from the given original (sender) SignerInfo.

The required receipt, sender message signature digest value and receipt content digest value are obtained from the SignerInfo, if available. If not available, an ESSException is thrown.

Parameters:
originatorSignerInfo - the signerInfo (of the original sender) from which to get required receipt and digest values
securityProvider - the SecurityProvider to be used by this object, if null, the default system-wide installed SecurityProvider is used; this constructor may use the SecurityProvider method getHash() to calculate the hash from the receipt content
sortAttributes - whether to sort the signed attributes when creating the SET OF encoding for MsgSigDigest value calculation; usually this will be set to true because a SenderAndReceiptContentDigest typically may be created on the sender side to be kept for later validation of the received signed receipt.
Throws:
ESSException - if the given SignerInfo cannot supply receipt or digest values as required

SenderAndReceiptContentDigest

public SenderAndReceiptContentDigest(ASN1Object obj)
                              throws CodingException
Creates a SenderAndReceiptContentDigest from an ASN.1 object.

A proprietary ASN.1 SEQUENCE is used to model this SenderAndReceiptContentDigest:

 SenderAndReceiptContentDigest ::=  SEQUENCE {        
   receipt              Receipt,
   senderMessageDigest  OCTET STRING,
   receiptContentDigest OCTET STRING}
 

Parameters:
obj - the ASN.1 object to be parsed
Throws:
CodingException - if an error occurs while parsing

SenderAndReceiptContentDigest

public SenderAndReceiptContentDigest(java.io.InputStream is)
                              throws java.io.IOException
Creates a SenderAndReceiptContentDigest from an input stream supplying the BER encoded SenderAndReceiptContentDigest.

Parameters:
is - the input stream from where to read the encoded object
Throws:
java.io.IOException - if an error occurs while reading from the stream
Method Detail

storeEntry

public static SenderAndReceiptContentDigest storeEntry(SenderAndReceiptContentDigest senderAndReceiptContentDigest)
Keep the given senderAndReceiptContentDigest for later Signed Receipt validation. This method puts the given senderAndReceiptContentDigest into the digest store hashtable by using the inherent Receipt as hashtable key. Any old entry with the same Receipt is replaced.

Parameters:
senderAndReceiptContentDigest - the SenderAndReceiptContentDigest to be kept
Returns:
the former SenderAndReceiptContentDigest, if present; null otherwise

removeEntry

public static SenderAndReceiptContentDigest removeEntry(SenderAndReceiptContentDigest senderAndReceiptContentDigest)
Removes the given senderAndReceiptContentDigest from the digest store.

Parameters:
senderAndReceiptContentDigest - the SenderAndReceiptContentDigest to be removed
Returns:
the removed SenderAndReceiptContentDigest; or null if no such object was present

removeEntry

public static SenderAndReceiptContentDigest removeEntry(Receipt receipt)
Removes the SenderAndReceiptContentDigest with the given Receipt from the digest store.

Parameters:
receipt - the Receipt identifying the SenderAndReceiptContentDigest to be removed
Returns:
the removed SenderAndReceiptContentDigest; or null if no SenderAndReceiptContentDigest for the given Receipt can be found

getEntry

public static SenderAndReceiptContentDigest getEntry(Receipt receipt)
Gets the SenderAndReceiptContentDigest with the given Receipt from the digest store.

Parameters:
receipt - the Receipt identifying the SenderAndReceiptContentDigest to get
Returns:
the SenderAndReceiptContentDigest; or null if no SenderAndReceiptContentDigest for the given Receipt can be found

getAllEntries

public static java.util.Enumeration getAllEntries()
Returns an Enumeration of all entries in the digest store.

Returns:
an enumeration of all entries in the digest store

clearDigestStore

public static void clearDigestStore()
Clears the digest store.


validateReceiptContent

public static SenderAndReceiptContentDigest validateReceiptContent(ReceiptContent receiptContent)
                                                            throws CMSException,
                                                                   ESSException
Validates the Signed Receipt according to section 2.6 (clause 3. to 6.) of RFC 2634.

This method first looks if a SenderAndReceiptContentDigest with the Receipt of the ReceiptContent to be validated has been kept. If yes, the MsgSigDigest attribute value of ReceiptContent-SignerInfo is compared with the kept sender message signature digest value and its MessageDigest attribute value is compared with the kept ReceiptContent message digest value.

Parameters:
receiptContent - the ReceiptContent to be validated
Returns:
the kept SenderAndReceiptContentDigest used for validation (i.e. the one with the same Receipt as the given ReceiptContent)
Throws:
CMSException - if some attribute parsing error occurs
ESSException - if the validation fails because any of the required digest values is not present or the digest comparison fails

initDigestStore

public static void initDigestStore(java.io.InputStream is)
                            throws java.io.IOException
Initializes the digest store from the given stream. This method may be used to init the digest store from an external source where it has been previously written by calling method writeDigestStore. Any existing entries are cleared before the store is initiailized.

Parameters:
is - the input stream from which to read
Throws:
java.io.IOException - if an error occurs while reading from the stream

writeDigestStore

public static void writeDigestStore(java.io.OutputStream os)
                             throws java.io.IOException
Writes the digest store contents to the given output stream. Any entry contributes as a component to an ASN.1 SEQUENCE. Use initDigestStore for reading the contents back.

Parameters:
os - the output stream to which to write the digest store
Throws:
java.io.IOException - if an error occurs while writing the store

getReceipt

public Receipt getReceipt()
Returns the receipt.

Returns:
the receipt

getSenderMessageDigest

public byte[] getSenderMessageDigest()
Returns the message signature digest value used by the sender to generate the original signedData signerInfo signature value.

Returns:
the sender message signature digest value

getReceiptContentDigest

public byte[] getReceiptContentDigest()
Returns the message digest value of the Receipt content

Returns:
the message digest value of the Receipt content

decode

public void decode(java.io.InputStream is)
            throws java.io.IOException
Reads and decodes a BER encoded SenderAndReceiptContentDigest from the given input stream.

A proprietary ASN.1 SEQUENCE is used to model this SenderAndReceiptContentDigest:

 SenderAndReceiptContentDigest ::=  SEQUENCE {        
   receipt              Receipt,
   senderMessageDigest  OCTET STRING,
   receiptContentDigest OCTET STRING}
 

Parameters:
is - the input stream from where to read the encoded SenderAndReceiptContentDigest
Throws:
java.io.IOException - if an error occurs while reading from the stream

decode

public void decode(ASN1Object obj)
            throws CodingException
Decodes the given ASN.1 SenderAndReceiptContentDigest object.

A proprietary ASN.1 SEQUENCE is used to model this SenderAndReceiptContentDigest:

 SenderAndReceiptContentDigest ::=  SEQUENCE {        
   receipt              Receipt,
   senderMessageDigest  OCTET STRING,
   receiptContentDigest OCTET STRING}
 

Parameters:
obj - the SenderAndReceiptContentDigest as ASN1Object
Throws:
CodingException - if the object cannot be paresd

toASN1Object

public ASN1Object toASN1Object()
Returns this SenderAndReceiptContentDigest as ASN1Object.

A proprietary ASN.1 SEQUENCE is used to model this SenderAndReceiptContentDigest:

 SenderAndReceiptContentDigest ::=  SEQUENCE {        
   receipt              Receipt,
   senderMessageDigest  OCTET STRING,
   receiptContentDigest OCTET STRING}
 

Returns:
this SenderAndReceiptContentDigest as ASN1Object

writeTo

public void writeTo(java.io.OutputStream os)
             throws CMSException,
                    java.io.IOException
Writes this ESS SenderAndReceiptContentDigest object BER encoded to the given output stream.

A proprietary ASN.1 SEQUENCE is used to model this SenderAndReceiptContentDigest:

 SenderAndReceiptContentDigest ::=  SEQUENCE {        
   receipt              Receipt,
   senderMessageDigest  OCTET STRING,
   receiptContentDigest OCTET STRING}
 

Parameters:
os - the output stream to which to write the SenderAndReceiptContentDigest
Throws:
CMSException - if an encoding error occurs
java.io.IOException - if an error occurs during writing to the stream

validate

public void validate(ReceiptContent receiptContent)
              throws CMSException,
                     ESSException
Validates the Signed Receipt according to section 2.6 (clause 3. to 6.) of RFC 2634.

Gets the SignerInfo from the ReceiptContent and compares its MsgSigDigest attribute value with the kept sender message signature digest value and its MessageDigest attribute value with the kept ReceiptContent message digest value. This method additionally compares the Receipt of the supplied receiptContent with the one of this SenderAndReceiptContentDigest.

Parameters:
receiptContent - the ReceiptContent to be validated
Throws:
CMSException - if some attribute parsing error occurs
ESSException - if the validation fails because any of the required digest values is not present or the digest comparison fails, or the Receipts do not match

toString

public java.lang.String toString()
Returns a string representation of this SenderAndReceiptContentDigest.

Overrides:
toString in class java.lang.Object
Returns:
this Receipt as string

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