public class AuthenticatedData extends AuthenticatedDataStream implements Content
AuthenticatedData type.
Each CMS content type is associated with a specific object identifier, derived from:
pkcs-9 OBJECT IDENTIFIER ::=
{ iso(1) member-body(2) US(840) rsadsi(113549)
pkcs(1) 9 }
The object identifier for the AuthenticatedData content type is
defined as:
id-ct-authData OBJECT IDENTIFIER ::= { pkcs-9 smime(16) ct(1) 2 }
which corresponds to the OID string "1.2.840.1.113549.1.9.16.1.2".
The Cryptographic Message Syntax
(CMS, RFC 5652) specifies the AuthenticatedData
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):
AuthenticatedData ::= SEQUENCE {
version Version,
originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
recipientInfos RecipientInfos,
macAlgorithm MessageAuthenticationCodeAlgorithm,
digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
encapContentInfo EncapsulatedContentInfo,
authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
mac MessageAuthenticationCode,
unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
MessageAuthenticationCode ::= OCTET STRING
If the digestAlgorithm field is not null, authenticated attributes have to be present and the MAC value is calculated on the DER encoding of the authenticated attributes. In this case the MessageDigest attribute has to be included as authenticated attribute and has to contain a digest value computed on the content data. If no authenticated attributes are present, the MAC value is computed on the content itself.
A recipient, when receiving the AuthenticatedData message, decrypts the corresponding encrypted mac key with his/her key and subsequently uses it to verify the message authentication code.
When creating an AuthenticatedData
object an application has to decide whether the to-be-authenticated content
shall be incldued (IMPLICIT mode) into the AuthenticatedData
message or shall be transmitted by other means (EXPLICIT mode):
int mode = AuthenticatedData.IMPLICIT; // include contentor
int mode = AuthenticatedData.EXPLICIT; // do not include contentHowever, in both cases the content data has to be supplied when creating the
AuthenticatedData object, because it is needed for the
MAC computation:
byte[] content = ...; // the content data to be authenticatedTogether with transmission mode and content data the following values have to be specified when creating an AuthenticatedData object, some of them are only optional:
SecurityProvider method generateKey. The IaikProvider tries to determine the block length
of the mac algorithm in use; otherwise it uses the
length of the underlying digest algorithm.
IMPLICIT (to include the content)
or EXPLICIT to transmit it by other means
originator information (if required by the
key management technique in use} maybe set via method setOriginatorInfo, and authenticated or unauthenticated attributes maybe
supplied by calling method setAuthenticatedAttributes
or setUnauthenticatedAttributes, respectively, e.g.:
// the content type
ObjectID contentType = ObjectID.cms_data;
// the content data to be authenticated
byte[] content = ...;
// the mac algorithm to be used
AlgorithmID macAlgorithm = (AlgorithmID)AlgorithmID.hMAC_SHA1.clone();
// the length of the mac key to be generated
int macKeyLength = 64;
// we do not need mac algorithm parameters
AlgorithmParameterSpec macParams = null;
// we want to include authenticated attributes and therefore need a digest algorithm
AlgorithmID digestAlgorithm = (AlgorithmID)AlgorithmID.sha1.clone();
// the transmission mode (either AuthenticatedData.IMPLICIT or AuthenticatedData.EXPLICIT)
int mode = ...;
// create the AuthenticatedData object:
AuthenticatedData authenticatedData = new AuthenticatedData(contentType,
content,
macAlgorithm,
macKeyLength,
macParams,
digestAlgorithm,
mode);
For providing origin authentication we use Static-Staic Diffie-Hellman as key management
technique and include an OriginatorInfo containing the originator certificates:
X509Certificate[] originatorCerts = ...; OriginatorInfo originator = new OriginatorInfo(); originator.setCertificates(originatorCerts); authenticatedData.setOriginatorInfo(originator);Just for demonstration we only add one authenticated attribute (
ContentType):
Attribute[] attributes = { new Attribute(new CMSContentType(contentType)) };
authenticatedData.setAuthenticatedAttributes(attributes);
When authenticated attributes are present they at least must contain the ContentType and the
(MessageDigest) attribute. It is not
necessary for the application to provide the MessageDigest attribute since it is
automatically calculated and set during the encoding procedure.
setRecipientInfos.
In our example we add two RecipientInfos (one for the the sender who wants to be able
to verify the MAC, too, and one for the final recipient). To provide origin authentication we
select Static-Static Diffie-Hellman as key management technique together with
HMACwith3DESwrap for encrypting (wrapping) the HMAC key:
RecipientInfo[] recipients = new RecipientInfo[1];
// we use Static-Static DH as key management technique
AlgorithmID keyEA = (AlgorithmID)AlgorithmID.ssdhKeyAgreement.clone();
// key wrap algorithm is HMACwith3DESwrap:
AlgorithmID keyWrapAlg = (AlgorithmID)CMSAlgorithmID.cms_HMACwith3DES_wrap.clone();
// the length of the (3DES) key encryption key to be generated:
int kekLength = 192;
// in static-static mode we supply user keying material so that a different kek is generated
byte[] ukm = new byte[64];
random.nextBytes(ukm);
// user1 is originator
recipients[0] = new KeyAgreeRecipientInfo(originatorCert,
originatorPrivateKey,
KeyIdentifier.ISSUER_AND_SERIALNUMBER,
keyEA,
keyWrapAlg,
kekLength,
ukm);
// add originator as recipient, too:
recipients[0].addRecipient(originatorCert, CertificateIdentifier.ISSUER_AND_SERIALNUMBER);
// add final recipient
recipients[0].addRecipient(recipientCert, CertificateIdentifier.RECIPIENT_KEY_IDENTIFIER);
// set the recipients of the authenticated message
authenticatedData.setRecipientInfos(recipients);
Finally the AuthenticatedData object has to be prepared for transmission by transforming
it into an ASN1Object or immediately DER encoding it. The former is done by calling method
toASN1Object, the latter by using method getEncoded method:
ASN1Object asn1AuthData = authenticatedData.toASN1Object();or
byte[] encoding = authenticatedData.getEncoded();You alternatively may use a proper
writeTo method of the parent
AuthenticatedDataStream class for immediately
encoding this AuthenticatedData 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 content 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 0xCAfor encoding the five data bytes
0x01 0xAB 0x23 0x7F 0xCA.
When receiving an AuthenticatedData message use the AuthenticatedData(InputStream) constructor for parsing the AuthenticatedData
from its DER encoding:
// the input stream supplying the DER encoded AuthenticatedData InputStream encodedStream = ...; // parse the AuthenticatedData AuthenticatedData authenticatedData = new AuthenticatedData(encodedStream);If the content has been transmitted by other means (
EXPLICIT mode) it
now has to be supplied by calling method setContent
since it is required for MAC computation (verification):
if (authenticatedData.getMode() == AuthenticatedData.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
byte[] content = ...; // the content received by other means
authenticatedData.setContent(content);
}
In order to decrypt the encrypted MAC key the recipient has to call a proper
setupMac method
thereby specifying her/his key encryption key which has to be suitable for the
key management technique that has been used. Since in our example both recipients have
used the key transport technique,
a private key is required to decrypt the encrypted mac key. The right
RecipientInfo maybe identified by the recipient certificate, e.g.:
// the recipient certificate: X509Certificate recipientCert = ...; // the corresponding private key PrivateKey recipientPrivateKey = ...; // setup the MAC by decrypting the secret MAC key autenticatedData.setupMac(recipientPrivateKey, recipientCert);After decrypting the encrypted MAC key, the MAC value can be verified by calling method
verifyMac:
// verify the MAC
try {
if (authenticatedData.verifyMac() == false) {
System.out.println("Invalid MAC value!");
}
} catch (CMSMacException ex) {
System.out.println("Mac verification error: " + ex.toString());
}
System.out.println("Mac successfully verified!");
Finally (in implicit mode) the content may be accessed by calling method
getContent:
byte[] content = authenticatedData.getContent();
AUTH_ATTRS_TAG, DIGEST_ALGORITHM_TAG, EXPLICIT, IMPLICIT, m_authAttrs, m_authKeyGenerated, m_blockSize, m_contentType, m_digestAlgorithm, m_digestInputStream, m_enableEncodeListener, m_encapContentInfo, m_enveloped_data, m_inputStream, m_inputStreamIsDigest, m_mac, m_mac_length, m_macAlgorithm, m_macAlgParameters, m_macInputStream, m_mode, m_originatorInfo, m_recipientInfos, m_secretKey, m_securityProvider, m_unauthAttrs, m_version, ORIGINATOR_INFO_TAG, UNAUTH_ATTRS_TAG| Modifier | Constructor and Description |
|---|---|
protected |
AuthenticatedData()
Default constructor for dynamic object creation in ContentInfoStream.
|
|
AuthenticatedData(java.io.InputStream is)
Creates an AuthenticatedData from a DER encoded AutheticatedData
object which is read from the given InputStream.
|
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlgorithm,
byte[] mac,
AlgorithmID digestAlgorithm,
int mode)
Creates an AuthenticatedDataStream from an already calculated MAC value.
|
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlgorithm,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macAlgParameters,
AlgorithmID digestAlgorithm,
int mode)
Creates a new AuthenticatedData where the to-be-authenticated content data is supplied from an byte array.
|
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlgorithm,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
int mode)
Creates a new AuthenticatedData where the to-be-authenticated content data is supplied from an byte array.
|
| Modifier and Type | Method and Description |
|---|---|
void |
decode(ASN1Object obj)
Decodes the given DigestedData ASN1 object.
|
void |
decode(java.io.InputStream is)
Reads and decodes the encoded AuthenticatedData from an input stream.
|
byte[] |
getContent()
Returns the content.
|
byte[] |
getEncoded()
Returns the DER encoding of this AuthenticatedData object as 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 data to be authenticated.
|
void |
setInputStream(java.io.InputStream is)
Sets the input stream that supplies the content data to
be autenticated.
|
protected ASN1Object |
toASN1Object(int blockSize)
Returns this
DigestedData as ASN1Object. |
addRecipientInfo, encodeCalled, getAuthenticatedAttribute, getAuthenticatedAttributes, getAuthenticatedDigest, getBlockSize, getContentType, getDigestAlgorithm, getEncapsulatedContentType, getMac, getMac, getMacAlgorithm, getMode, getOriginatorInfo, getRecipientInfo, getRecipientInfo, getRecipientInfos, getRecipientInfos, getUnauthenticatedAttribute, getUnauthenticatedAttributes, getVersion, notifyEOF, setAuthenticatedAttributes, setBlockSize, setOriginatorInfo, setRecipientInfos, setUnauthenticatedAttributes, setupMac, setupMac, setupMac, setupMac, toASN1Object, toString, toString, verifyMac, writeTo, writeToclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitgetBlockSize, getContentType, setBlockSize, toASN1Object, toStringprotected AuthenticatedData()
public AuthenticatedData(java.io.InputStream is)
throws java.io.IOException,
CMSParsingException
is - the InputStream supplying a DER encoded CMS AutheticatedData objectjava.io.IOException - if an I/O error occurs during reading from the InputStreamCMSParsingException - if an error occurs while parsing the objectpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlgorithm, byte[] mac, AlgorithmID digestAlgorithm, int mode) throws CMSException
contentType - the content type of the data to be digestedcontent - the data to be digested supplied from an input streammacAlgorithm - - the OID of the MAC algorithm used for mac calculationmac - - the already calculated mac valuedigestAlgorithm - - the OID of the digest algorithm used for hash calculationmode - - the transmissiom mode; either IMPLICIT (to include the content) or
EXPLICIT to transmit it by other meansCMSException - if the supplied parameters to not satisfy the requirements
or there is no implementation for the requested hash
algorithmpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlgorithm, int macKeyLength, java.security.spec.AlgorithmParameterSpec macAlgParameters, AlgorithmID digestAlgorithm, int mode) throws CMSException
contentType - the type of the authenticated content (e.g. ObjectID.cms_data)content - the to-be-authenticated datamacAlgorithm - the OID of the MAC algorithm to be usedmacKeyLength - the length (in bytes) of the mac key to be generated; if not specified (-1)macAlgParameters - any parameters, if required by the mac algorithmdigestAlgorithm - the OID of the digest algorithm to be used for hash computation if authenticated attributes are to be includedmode - the transmissiom mode; either IMPLICIT (to include the content) or EXPLICIT to transmit it by other meansCMSExceptionpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlgorithm, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, int mode) throws CMSException
contentType - the type of the authenticated content (e.g. ObjectID.cms_data)content - the to-be-authenticated datamacAlgorithm - the OID of the MAC algorithm to be usedmacKeyLength - the length (in bytes) of the mac key to be generated; if not specified (-1)macParams - any parameters, if required by the mac algorithmmode - the transmissiom mode; either IMPLICIT (to include the content) or EXPLICIT to transmit it by other meansCMSExceptionpublic void decode(ASN1Object obj) throws CMSParsingException
decode in interface Contentobj - the ASN1Object representing an already exisiting DigestedData objectCMSParsingException - if an error occurs when parsing the given ASN1Objectpublic void decode(java.io.InputStream is)
throws java.io.IOException,
CMSParsingException
decode in interface ContentStreamdecode in class AuthenticatedDataStreamis - the InputStream supplying a DER encoded CMS DigestedData objectjava.io.IOException - if an I/O error occurs during reading from the InputStreamCMSParsingException - if an error occurs while parsing the objectpublic byte[] getContent()
public byte[] getEncoded()
throws CMSException
CMSException - if an error occurs durin gthe encoding procedurepublic java.io.InputStream getInputStream()
This method only overrides the corresponding getInputStream method
of the parent AuthenticatedDataStream
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.
getInputStream in class AuthenticatedDataStreamDigestedData objectpublic void setContent(byte[] content)
content - - the content data to authenticatedpublic void setInputStream(java.io.InputStream is)
This method entirely reads the supplied stream.
setInputStream in class AuthenticatedDataStreamis - the input stream holding the content data to be authenticatedprotected ASN1Object toASN1Object(int blockSize) throws CMSException
DigestedData as ASN1Object.
The ASN1Object returned by this method may be used as parameter value when
creating a DigestedData object using the
DigestedData(ASN1Object)
constructor.
toASN1Object in class AuthenticatedDataStreamblockSize - the block size to be used for block oriented encodingDigestedData as ASN1Object.CMSException - if the ASN1Object could not be created