iaik.smime.ess
Class Receipt

java.lang.Object
  extended by iaik.smime.ess.Receipt
All Implemented Interfaces:
Content, ContentStream

public class Receipt
extends java.lang.Object
implements Content

The S/MIMEv3 ESS Receipt content type.

The Enhanced Security Services for S/MIMEv3 (ESS) (RFC 2634) specifies the Receipt content type to be set as content of a SignedData which shall be sent in response to a ReceiptRequest received:

 Receipt ::= SEQUENCE {
   version ESSVersion,
   contentType ContentType,
   signedContentIdentifier ContentIdentifier,
   originatorSignatureValue OCTET STRING }
 
 id-ct-receipt OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
   rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-ct(1) 1}

 ESSVersion ::= INTEGER  { v1(1) }
 
When receiving a SignedData having any SignerInfo holding a ReceiptRequest the recipient first has to check if all ReceiptRequests contained in any of the SignerInfos are identical. According to the rules given in RFC 2634, section 2.3, the recipient then checks if it is requested to create signed receipt(s) to be sent to dedicated user(s). If a signed receipt has to be sent, the recipient performs the following steps for creating the signed receipt and setting it as content of a SignedData object ("signedData/Receipt", see RFC 2634, section 2.4):
  1. The signature of the original signedData signerInfo that includes the receiptRequest signed attribute MUST be successfully verified before creating the signedData/Receipt.
  2. A Receipt structure is created.
  3. The Receipt structure is ASN.1 DER encoded to produce a data stream, D1.
  4. D1 is digested. The resulting digest value is included as the messageDigest attribute in the signedAttributes of the signerInfo which will eventually contain the signedData/Receipt signature value.
  5. The digest value (msgSigDigest) calculated in Step 1 to verify the signature of the original signedData signerInfo is included as the msgSigDigest attribute in the signedAttributes of the signerInfo which will eventually contain the signedData/Receipt signature value.
  6. A contentType attribute including the id-ct-receipt object identifier MUST be created and added to the signed attributes of the signerInfo which will eventually contain the signedData/Receipt signature value.
  7. A signingTime attribute indicating the time that the signedData/Receipt is signed SHOULD be created and added to the signed attributes of the signerInfo which will eventually contain the signedData/Receipt signature value. Other attributes (except receiptRequest) may be added to the signedAttributes of the signerInfo.
  8. The signedAttributes (messageDigest, msgSigDigest, contentType and, possibly, others) of the signerInfo are ASN.1 DER encoded and digested as described in CMS (RFC 5652). The resulting digest value is used to calculate the signature value which is then included in the signedData/Receipt signerInfo.
  9. The ASN.1 DER encoded Receipt content MUST be directly encoded within the signedData encapContentInfo eContent OCTET STRING defined in CMS (RFC 5652). The id-ct-receipt object identifier MUST be included in the signedData encapContentInfo eContentType. This results in a single ASN.1 encoded object composed of a signedData including the Receipt content. The Data content type MUST NOT be used. The Receipt content MUST NOT be encapsulated in a MIME header or any other header prior to being encoded as part of the signedData object.
  10. The signedData/Receipt is then put in an application/pkcs7-mime MIME wrapper with the smime-type parameter set to "signed-receipt". This will allow for identification of signed receipts without having to crack the ASN.1 body. The smime-type parameter would still be set as normal in any layer wrapped around this message.
  11. If the signedData/Receipt is to be encrypted within an envelopedData object, then an outer signedData object MUST be created that encapsulates the envelopedData object, and a contentHints attribute with contentType set to the id-ct-receipt object identifier MUST be included in the outer signedData SignerInfo signedAttributes. When a receiving agent processes the outer signedData object, the presence of the id-ct-receipt OID in the contentHints contentType indicates that a signedData/Receipt is encrypted within the envelopedData object encapsulated by the outer signedData.
When receiving a signed receipt the following steps have to be performed for validating the signed receipt (see RFC 2634, section 2.6):
  1. ASN.1 decode the signedData object including the Receipt content.
  2. Extract the contentType, signedContentIdentifier, and originatorSignatureValue from the decoded Receipt structure to identify the original signedData signerInfo that requested the signedData/Receipt.
  3. Acquire the message signature digest value calculated by the sender to generate the signature value included in the original signedData signerInfo that requested the signedData/Receipt.
  4. The message signature digest value calculated by the sender is then compared with the value of the msgSigDigest signedAttribute included in the signedData/Receipt signerInfo. If these digest values are identical, then that proves that the message signature digest value calculated by the recipient based on the received original signedData object is the same as that calculated by the sender. This proves that the recipient received exactly the same original signedData content and signedAttributes as sent by the sender because that is the only way that the recipient could have calculated the same message signature digest value as calculated by the sender. If the digest values are different, then the signedData/Receipt signature verification process fails.
  5. Acquire the digest value calculated by the sender for the Receipt content constructed by the sender (including the contentType, signedContentIdentifier, and signature value that were included in the original signedData signerInfo that requested the signedData/Receipt).
  6. The Receipt content digest value calculated by the sender is then compared with the value of the messageDigest signedAttribute included in the signedData/Receipt signerInfo. If these digest values are identical, then that proves that the values included in the Receipt content by the recipient are identical to those that were included in the original signedData signerInfo that requested the signedData/Receipt. This proves that the recipient received the original signedData signed by the sender, because that is the only way that the recipient could have obtained the original signedData signerInfo signature value for inclusion in the Receipt content. If the digest values are different, then the signedData/Receipt signature verification process fails.
  7. The ASN.1 DER encoded signedAttributes of the signedData/Receipt signerInfo are digested as described in CMS (RFC 5652).
  8. The resulting digest value is then used to verify the signature value included in the signedData/Receipt signerInfo. If the signature verification is successful, then that proves the integrity of the signedData/receipt signerInfo signedAttributes and authenticates the identity of the signer of the signedData/Receipt signerInfo. Note that the signedAttributes include the recipient-calculated Receipt content digest value (messageDigest attribute) and recipient-calculated message signature digest value (msgSigDigest attribute). Therefore, the aforementioned comparison of the sender-generated and recipient-generated digest values combined with the successful signedData/Receipt signature verification proves that the recipient received the exact original signedData content and signedAttributes (proven by msgSigDigest attribute) that were signed by the sender of the original signedData object (proven by messageDigest attribute). If the signature verification fails, then the signedData/Receipt signature verification process fails.
When creating a new Receipt you may specify the content type, signed content identifier and originator signature value immediately:
 ObjectID contentType = ...;
 ContentIdentifier contentIdentifier = ...;
 byte[] originatorSignatureValue = ...;
 Receipt Receipt = 
   new Receipt(contentType, contentIdentifier, originatorSignatureValue);
 
Or you may create a Receipt from a SignerInfo letting the constructor get the required information from the SignerInfo to set the fields of the Receipt as required:
 SignerInfo signerInfo = ...;
 Receipt receipt = new Receipt(signerInfo);
 

See Also:
ReceiptRequest, ContentIdentifier, SignerInfo, SignedData

Field Summary
static ObjectID oid
          The content type object identifier of the Receipt structure.
 
Constructor Summary
Receipt()
          Empty default constructor.
Receipt(ASN1Object obj)
          Creates an Receipt from its ASN.1 representation.
Receipt(java.io.InputStream is)
          Creates a Receipt from an input stream supplying the DER encoded Receipt.
Receipt(ObjectID contentType, ContentIdentifier signedContentIdentifier, byte[] originatorSignatureValue)
          Creates an Receipt from given content type, content identifier and originator signature value.
Receipt(SignerInfo signerInfo)
          Creates an Receipt from the given SignerInfo.
 
Method Summary
 void decode(ASN1Object obj)
          Decodes the given ASN.1 Receipt object for parsing the internal structure.
 void decode(java.io.InputStream is)
          Reads and decodes a DER encoded Receipt from the given input stream.
 boolean equals(java.lang.Object obj)
          Compares this Receipt to the specified object.
 int getBlockSize()
          Returns -1.
 ObjectID getContentType()
          Returns the ESS Receipt (id-cd-receipt) content type object identifier.
 byte[] getEncoded()
          DER encodes this ESS Receipt object.
 byte[] getOriginatorSignatureValue()
          Returns the originator signature value.
 ObjectID getReceiptContentType()
          Returns the content type.
 SecurityProvider getSecurityProvider()
          Returns null since no SecurityProvider is required by this class.
 ContentIdentifier getSignedContentIdentifier()
          Returns the signed content identifier.
 int getVersion()
          Gets the ESSVersion number.
 int hashCode()
          Returns a hashcode for this Receipt.
 void setBlockSize(int blockSize)
          Does nothing.
 void setSecurityProvider(SecurityProvider securityProvider)
          Does nothing since no SecurityProvider is required by this class.
 ASN1Object toASN1Object()
          Returns this Receipt as ASN1Object.
 java.lang.String toString()
          Returns a string representation of this Receipt.
 java.lang.String toString(boolean detailed)
          Returns a string representation of this Receipt.
 void writeTo(java.io.OutputStream os)
          Writes this ESS Receipt object DER encoded to the given output stream.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

oid

public static final ObjectID oid
The content type object identifier of the Receipt structure. The corresponding OID string is "1.2.840.113549.1.9.16.1.1".

Constructor Detail

Receipt

public Receipt()
Empty default constructor. Required for dynamic object creation. Shall NOT be used by an application.


Receipt

public Receipt(ObjectID contentType,
               ContentIdentifier signedContentIdentifier,
               byte[] originatorSignatureValue)
Creates an Receipt from given content type, content identifier and originator signature value.

Parameters:
contentType - the content type of the of the SignedData to be linked to
signedContentIdentifier - the signed content identifier of the SignedData to be linked to
originatorSignatureValue - the signature value of the SignedData to be linked to

Receipt

public Receipt(SignerInfo signerInfo)
        throws ESSException
Creates an Receipt from the given SignerInfo.

This constructor follows the instructions given in RFC 2634, section 2.4, 2:

This constructor just creates a Receipt as described above, but does not perform any signature or ReceiptRequest validation.

Parameters:
signerInfo - the signerInfo from which to create a Receipt
Throws:
ESSException - if the Receipt cannot be created for some reason, e.g. no ReceiptRequest is included in the supplied SignerInfo

Receipt

public Receipt(java.io.InputStream is)
        throws java.io.IOException,
               CMSParsingException
Creates a Receipt from an input stream supplying the DER encoded Receipt.

Parameters:
is - the input stream from where to read the encoded Receipt
Throws:
CMSParsingException - if the object cannot be paresd
java.io.IOException - if an error occurs while reading from the stream

Receipt

public Receipt(ASN1Object obj)
        throws CMSParsingException
Creates an Receipt from its ASN.1 representation.

Parameters:
obj - the Receipt as ASN1Object
Throws:
CMSParsingException - if the object cannot be paresd
Method Detail

setSecurityProvider

public void setSecurityProvider(SecurityProvider securityProvider)
Does nothing since no SecurityProvider is required by this class. Only required to implement the ContentStream interface.

Parameters:
securityProvider - the SecurityProvider to be set; ignored

getSecurityProvider

public SecurityProvider getSecurityProvider()
Returns null since no SecurityProvider is required by this class. Only required to implement the ContentStream interface.

Returns:
null

getVersion

public int getVersion()
Gets the ESSVersion number.

Returns:
the ESSVersion number (1) this Receipt conforms to

getBlockSize

public int getBlockSize()
Returns -1. Only implements the same name method of the Content interface, but has no meaning here.

Specified by:
getBlockSize in interface ContentStream
Returns:
-1

setBlockSize

public void setBlockSize(int blockSize)
Does nothing. Only implements the same name method of the Content interface., but has no meaning here.

Specified by:
setBlockSize in interface ContentStream
Parameters:
blockSize - the block size; ignored here

getReceiptContentType

public ObjectID getReceiptContentType()
Returns the content type.

Attention! The OID returned by this method is the content type as given in the second component of an Receipt object and represents the value of the contentType attribute included in the original signedData signerInfo that includes the receiptRequest:

 Receipt ::= SEQUENCE {
   version ESSVersion,
   contentType ContentType,
   signedContentIdentifier ContentIdentifier,
   originatorSignatureValue OCTET STRING }
 
It has to be distinguished from the content type returned by method getContentType which always returns the id-cd-receipt oid.

Returns:
the receipt content type

getSignedContentIdentifier

public ContentIdentifier getSignedContentIdentifier()
Returns the signed content identifier.

Returns:
the signed content identifier

getOriginatorSignatureValue

public byte[] getOriginatorSignatureValue()
Returns the originator signature value.

Returns:
the originator signature value

equals

public boolean equals(java.lang.Object obj)
Compares this Receipt to the specified object.

Overrides:
equals in class java.lang.Object
Parameters:
obj - the object to compare this Receipt against.
Returns:
true, if the given object is equal to this Receipt, false otherwise

hashCode

public int hashCode()
Returns a hashcode for this Receipt.

Overrides:
hashCode in class java.lang.Object
Returns:
a hashcode for this Receipt

decode

public void decode(java.io.InputStream is)
            throws java.io.IOException,
                   CMSParsingException
Reads and decodes a DER encoded Receipt from the given input stream.

Specified by:
decode in interface ContentStream
Parameters:
is - the input stream from where to read the encoded Receipt
Throws:
CMSParsingException - if the object cannot be paresd
java.io.IOException - if an error occurs while reading from the stream

decode

public void decode(ASN1Object obj)
            throws CMSParsingException
Decodes the given ASN.1 Receipt object for parsing the internal structure.

Specified by:
decode in interface Content
Parameters:
obj - the Receipt as ASN1Object
Throws:
CMSParsingException - if the object cannot be paresd

toASN1Object

public ASN1Object toASN1Object()
Returns this Receipt as ASN1Object.

Specified by:
toASN1Object in interface ContentStream
Returns:
this Receipt as ASN1Object

getContentType

public ObjectID getContentType()
Returns the ESS Receipt (id-cd-receipt) content type object identifier.

Attention! This method implements the smae name method of the Content interface to always return the id-ct-receipt oid. The content type returned by this method has to be distinguished from the content type returned by method getReceiptContentType() which returns the content type as given in the second component of an Receipt object:

 Receipt ::= SEQUENCE {
   version ESSVersion,
   contentType ContentType,
   signedContentIdentifier ContentIdentifier,
   originatorSignatureValue OCTET STRING }
 

Specified by:
getContentType in interface ContentStream
Returns:
the ESS Receipt (id-cd-receipt) content type object identifier

toString

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

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

toString

public java.lang.String toString(boolean detailed)
Returns a string representation of this Receipt.

Specified by:
toString in interface ContentStream
Parameters:
detailed - whether to give detailed information
Returns:
this Receipt as string

getEncoded

public byte[] getEncoded()
                  throws CMSException
DER encodes this ESS Receipt object.

Returns:
the DER encoded Receipt object
Throws:
CMSException - if an encoding error occurs

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException
Writes this ESS Receipt object DER encoded to the given output stream.

Parameters:
os - the output stream to which to encode the Receipt
Throws:
java.io.IOException - if an error occurs during encoding to the stream

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