public class AuthenticatedDataStream extends java.lang.Object implements ContentStream, EncodeListener, EOFListener
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(9) smime(16) ct(1) 2 }
which corresponds to the OID string "1.2.840.113549.1.9.16.1.2".
The Cryptographic Message Syntax
(CMS, RFC 5652) specifies the AuthenticatedData content
type for providing a syntax for recipient-specific protecting the integrity
of a message by means of a Message Authentication Code (MAC). Content of any
type may be authenticated for any number of recipients in parallel. For each
recipient a randomly generated symmetric mac key is encrypted with
the particular recipient key and - together with recipient-specific
information - collected into a RecipientInfo value. A message authentication
code on the content is computed with the mac key and -- together with the
RecipientInfos objects -- packed into a AuthenticatedData message.
The AuthenticatedData content type is defined as:
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 an 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.
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);
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).
// 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();
| Modifier and Type | Field and Description |
|---|---|
protected static int |
AUTH_ATTRS_TAG |
protected static int |
DIGEST_ALGORITHM_TAG |
static int |
EXPLICIT
Denotes a mode where the content is included within the AuthenticatedData
|
static int |
IMPLICIT
Denotes a mode where the content is not transmitted within the
AuthenticatedData
|
protected Attributes |
m_authAttrs
The authenticated attributes
|
protected boolean |
m_authKeyGenerated
A flag to indicate if the authenticated key has been generated
|
protected int |
m_blockSize
The block size for block oriented stream encoding.
|
protected ObjectID |
m_contentType
The content type.
|
protected AlgorithmID |
m_digestAlgorithm
The digest algorithm to use.
|
protected java.security.DigestInputStream |
m_digestInputStream
A class variable used to reference the DigetInputStream that
wraps the InputStream.
|
protected boolean |
m_enableEncodeListener
Variable used to determine whether the encode listener should be used
(for streaming support), or whether it should not be used (non-stream support)
|
protected EncapsulatedContentInfoStream |
m_encapContentInfo
The inherent EncapsualtedContentInfo.
|
protected DerInputStream |
m_enveloped_data
An
InputStream holding the authenticated data. |
protected java.io.InputStream |
m_inputStream
An InputStream holding the data
|
protected boolean |
m_inputStreamIsDigest
This boolean flag is used to indicate if the underlying input stream
used is a DigestInputStream.
|
protected byte[] |
m_mac
The Mac value
|
protected int |
m_mac_length
The length of the Mac
|
protected AlgorithmID |
m_macAlgorithm
The MAC algorithm to use.
|
protected java.security.spec.AlgorithmParameterSpec |
m_macAlgParameters
The MAC AlgorithmParameterSpec
|
protected MacInputStream |
m_macInputStream
A class variable used to reference the MacInputStream that
wraps the InputStream.
|
protected int |
m_mode
The mode specifying if the data shall be included (IMPLICIT), or if is
not included (EXPLICIT).
|
protected OriginatorInfo |
m_originatorInfo
The originator Information encapsulated in an Object
|
protected java.util.Vector<RecipientInfo> |
m_recipientInfos
A list of RecipientInfo
|
protected javax.crypto.SecretKey |
m_secretKey
The Symmetric Mac Key (Message Authentication Key)
|
protected SecurityProvider |
m_securityProvider
The SecurityProvider to be used.
|
protected Attributes |
m_unauthAttrs
The unauthenticated attributes
|
protected int |
m_version
The CMS version number.
|
protected static int |
ORIGINATOR_INFO_TAG |
protected static int |
UNAUTH_ATTRS_TAG |
| Modifier | Constructor and Description |
|---|---|
protected |
AuthenticatedDataStream()
Default constructor for dynamic object creation in ContentInfoStream.
|
|
AuthenticatedDataStream(java.io.InputStream is)
Creates an AuthenticatedDataStream from a BER encoded AutheticatedData object which is read
from the given InputStream.
|
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream data_is,
AlgorithmID macAlgorithm,
byte[] mac,
AlgorithmID digestAlgorithm,
int mode)
Creates an AuthenticatedDataStream from an already calculated MAC value.
|
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream data_is,
AlgorithmID macAlgorithm,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macAlgParameters,
AlgorithmID digestAlgorithm,
int mode)
Creates a new AuthenticatedDataStream where the to-be-authenticated
content data is supplied by an input stream.
|
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream data_is,
AlgorithmID macAlgorithm,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macAlgParameters,
int mode)
Creates a new AuthenticatedDataStream where the to-be-authenticated
content data is supplied by an input stream.
|
| Modifier and Type | Method and Description |
|---|---|
void |
addRecipientInfo(RecipientInfo recipientinfo)
Adds one recipient to the list of recipient infos
Any
RecipientInfo added supplies recipient-specific information used for
identifying the key of the recipient to be used for en/decrypting the symmetric mac key |
void |
decode(java.io.InputStream is)
Reads and decodes a BER encoded DigestedData from an input stream.
|
void |
encodeCalled(ASN1Object asn1,
int id)
This method implements the EncodeListener interface.
|
Attribute |
getAuthenticatedAttribute(ObjectID objectid) |
Attribute[] |
getAuthenticatedAttributes() |
byte[] |
getAuthenticatedDigest()
Return the authenticated Digested which is alreay included in the authenticated
Attributes.
|
int |
getBlockSize()
Gets the block size defining the length of each definite primitive
encoded octet string component.
|
ObjectID |
getContentType()
Returns the content type this class implements.
|
AlgorithmID |
getDigestAlgorithm()
Returns the message-digest algorithm used for computing the digest.
|
ObjectID |
getEncapsulatedContentType()
Returns the content type the inherent EncapsulatetContentInfo represents.
|
java.io.InputStream |
getInputStream()
Returns an input stream with the raw data.
|
byte[] |
getMac() |
javax.crypto.Mac |
getMac(AlgorithmID algorithmid,
java.security.Key key,
java.security.spec.AlgorithmParameterSpec algorithmparameterspec) |
AlgorithmID |
getMacAlgorithm()
Returns the message-digest algorithm used for computing the digest.
|
int |
getMode() |
OriginatorInfo |
getOriginatorInfo() |
RecipientInfo |
getRecipientInfo(KeyIdentifier recipientIdentifier) |
RecipientInfo |
getRecipientInfo(X509Certificate recipientCertificate) |
RecipientInfo[] |
getRecipientInfos() |
RecipientInfo[] |
getRecipientInfos(int type) |
Attribute |
getUnauthenticatedAttribute(ObjectID objectid) |
Attribute[] |
getUnauthenticatedAttributes() |
int |
getVersion() |
void |
notifyEOF()
This method implements the EOFListener interface for performing the final
decoding.
|
void |
setAuthenticatedAttributes(Attribute[] attributes)
Sets a set of (authenticated) attributes.
|
void |
setBlockSize(int blockSize)
Sets the block size for defining the length of each definite primitive
encoded octet string component.
|
void |
setInputStream(java.io.InputStream is)
Sets the content suppliyng input stream.
|
void |
setOriginatorInfo(OriginatorInfo originatorInfo)
Sets the optional OriginatorInfo.
|
void |
setRecipientInfos(RecipientInfo[] recipients)
Sets the recipient infos:
Any RecipientInfo added supplies recipient-specific information used for identifying the key of the
recipient to be used for en/decrypting the symmetric mac key.
|
void |
setUnauthenticatedAttributes(Attribute[] attributes)
Sets a set of (unauthenticated) attributes.
|
javax.crypto.SecretKey |
setupMac(java.security.Key recipientKey,
int recipientInfoIndex)
Uses the specified key for decrypting the MAC key and setting the MAC calculation
for the requesting recipient, specified by its recipientInfoIndex.
|
javax.crypto.SecretKey |
setupMac(java.security.Key recipientKey,
KeyIdentifier recipientIdentifier)
Uses the specified key for decrypting the MAC key and setup the MAC calculation for the
requesting recipient, specified by the given recipient identifier.
|
javax.crypto.SecretKey |
setupMac(java.security.Key recipientKey,
X509Certificate recipientCertificate)
Uses the specified key for decrypting the MAC key and setup the MAC calculation for the
requesting recipient, specified by the given recipient identifier.
|
void |
setupMac(javax.crypto.SecretKey macKey)
Uses the given symmetric key to setup the MAC calculation to verify the message
authentication code when parsing an AuthenticatedData object.
|
ASN1Object |
toASN1Object()
Returns this DigestedDataStream as ASN1Object.
|
protected ASN1Object |
toASN1Object(int blockSize)
Returns this DigestedData as ASN1Object where a constructed OCTET STRING
is used for encoding the content.
|
java.lang.String |
toString() |
java.lang.String |
toString(boolean detailed)
Returns a string giving some information about this
DigestedData object. |
boolean |
verifyMac()
Verifies the message authentication code.
|
void |
writeTo(java.io.OutputStream os)
Writes this DigestedData DER encoded to the supplied output stream.
|
void |
writeTo(java.io.OutputStream os,
int blockSize)
Writes this object to the supplied output stream where a constructed
OCTET STRING is used for encoding the content.
|
protected static final int UNAUTH_ATTRS_TAG
protected static final int AUTH_ATTRS_TAG
protected static final int DIGEST_ALGORITHM_TAG
protected static final int ORIGINATOR_INFO_TAG
public static final int IMPLICIT
public static final int EXPLICIT
protected boolean m_enableEncodeListener
protected int m_version
protected AlgorithmID m_macAlgorithm
protected byte[] m_mac
protected int m_mac_length
protected AlgorithmID m_digestAlgorithm
protected ObjectID m_contentType
protected int m_blockSize
protected javax.crypto.SecretKey m_secretKey
protected EncapsulatedContentInfoStream m_encapContentInfo
protected java.io.InputStream m_inputStream
protected java.security.DigestInputStream m_digestInputStream
protected MacInputStream m_macInputStream
protected boolean m_inputStreamIsDigest
If set to true, then the Digest is calculated as part of the Authenticated Attributes:
If authAttrs field is present, the content-type attribute (as described in Section 11.1) and the message-digest attribute (as described in section 11.2) MUST be included, and the input to the MAC calculation process is the DER encoding of authAttrs.If set to false, then the MAC is calculated over the OCTET_String contents:
If authAttrs field is absent, the input to the MAC calculation process is the value of the encapContentInfo eContent OCTET STRING.
protected int m_mode
protected OriginatorInfo m_originatorInfo
protected java.util.Vector<RecipientInfo> m_recipientInfos
protected boolean m_authKeyGenerated
protected Attributes m_authAttrs
protected Attributes m_unauthAttrs
protected DerInputStream m_enveloped_data
InputStream holding the authenticated data.protected SecurityProvider m_securityProvider
protected java.security.spec.AlgorithmParameterSpec m_macAlgParameters
protected AuthenticatedDataStream()
public AuthenticatedDataStream(java.io.InputStream is)
throws java.io.IOException,
CMSParsingException
is - the InputStream holding the BER encoded CMS AuthenticatedData objectjava.io.IOException - if an error occurs when reasding from the streamCMSParsingException - if the object can not be parsedpublic AuthenticatedDataStream(ObjectID contentType, java.io.InputStream data_is, AlgorithmID macAlgorithm, byte[] mac, AlgorithmID digestAlgorithm, int mode) throws CMSException
contentType - the content type of the data to be digesteddata_is - 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 transmission 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream data_is, AlgorithmID macAlgorithm, int macKeyLength, java.security.spec.AlgorithmParameterSpec macAlgParameters, AlgorithmID digestAlgorithm, int mode) throws CMSException
contentType - the content type of the data to be digesteddata_is - the data to be digested supplied from an input streammacAlgorithm - - the OID of the MAC algorithm to be usedmacKeyLength - - the length (in bytes) of the MAC key to be generated; if not specified (-1),
a default value will be used depending on the MAC algorithm and the implementation of the
SecurityProvider method generateKey. The toolkit tries to determine the block length of the MAC
algorithm in use; otherwise it uses the length of the underlying digest algorithm.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 transmission 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream data_is, AlgorithmID macAlgorithm, int macKeyLength, java.security.spec.AlgorithmParameterSpec macAlgParameters, int mode) throws CMSException
contentType - the type of the authenticated content (e.g. ObjectID.cms_data)data_is - an input stream supplying 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), a default value will
be used depending on the MAC algorithm and the
implementation of the SecurityProvider method
generateKey. The toolkit tries to determine the
block length of the MAC algorithm in use; otherwise it
uses the length of the underlying digest algorithm.macAlgParameters - - any parameters, if required by the MAC algorithmmode - - the transmission 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 void addRecipientInfo(RecipientInfo recipientinfo)
RecipientInfo added supplies recipient-specific information used for
identifying the key of the recipient to be used for en/decrypting the symmetric mac keyrecipientinfo - the RecipientInfo to be addedpublic void decode(java.io.InputStream is)
throws java.io.IOException,
CMSParsingException
decode in interface ContentStreamis - the InputStream holding a BER 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 void encodeCalled(ASN1Object asn1, int id) throws CodingException
EncodeListener
utility. The toASN1Object() method of this AuthenticatedDataStream
class instantiates an empty OCTET_STRING for the digest field, and registers
itself as EncodeListener for this empty OCTET_STRING. Now, during the encoding
process, when the content stream entirely has been read, this
encodeCalled method is called for performing digest
computation. The supplied ASN1Object is the empty OCTET_STRING to be
"filled" with the result of the digest-computation.encodeCalled in interface EncodeListenerasn1 - The ASN1Object which will append the digest and MAC values during
the encoding of the stream.id - the id identifying the particular component to be processed, not used by
this implementation.CodingException - if an error occurs when computing/encrypting the message
digestpublic javax.crypto.Mac getMac(AlgorithmID algorithmid, java.security.Key key, java.security.spec.AlgorithmParameterSpec algorithmparameterspec) throws java.security.InvalidAlgorithmParameterException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.NoSuchProviderException
algorithmid - The algorithmID for the Mac algorithmkey - The Key used to initilaize the MAC algorithmalgorithmparameterspec - The algorihtm parameters if required.java.security.InvalidAlgorithmParameterExceptionjava.security.NoSuchAlgorithmExceptionjava.security.InvalidKeyExceptionjava.security.NoSuchProviderExceptionpublic Attribute getAuthenticatedAttribute(ObjectID objectid)
objectid - public Attribute[] getAuthenticatedAttributes()
public int getBlockSize()
blockSize is
smaller or equal to zero the whole data is encoded as definite primitive
octet string.getBlockSize in interface ContentStreampublic ObjectID getContentType()
getContentType in interface ContentStreamObjectID.cms_authDatapublic AlgorithmID getDigestAlgorithm()
public ObjectID getEncapsulatedContentType()
public java.io.InputStream getInputStream()
public byte[] getMac()
public AlgorithmID getMacAlgorithm()
public int getMode()
public OriginatorInfo getOriginatorInfo()
public RecipientInfo getRecipientInfo(KeyIdentifier recipientIdentifier)
recipientIdentifier - public RecipientInfo getRecipientInfo(X509Certificate recipientCertificate)
recipientCertificate - the recipient Certificatepublic RecipientInfo[] getRecipientInfos()
public RecipientInfo[] getRecipientInfos(int type)
type - the RecipientInfo typeRecipientInfopublic Attribute getUnauthenticatedAttribute(ObjectID objectid)
objectid - the objectID of the unauthenticated attributepublic Attribute[] getUnauthenticatedAttributes()
public int getVersion()
public void notifyEOF()
throws java.io.IOException
notifyEOF method
for finishing the decoding by parsing the final unauthenticated attributes field. notifyEOF in interface EOFListenerjava.io.IOExceptionpublic void setAuthenticatedAttributes(Attribute[] attributes)
public void setBlockSize(int blockSize)
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 DigestedData into a ContentInfo.setBlockSize in interface ContentStreamblockSize - for defining the encoding scheme and setting the octet string
component length, if positivepublic void setInputStream(java.io.InputStream is)
is - the input stream holding the content data to be authenticatedpublic void setOriginatorInfo(OriginatorInfo originatorInfo)
originatorInfo - The OriginatorInfo object representing information about message originationpublic void setRecipientInfos(RecipientInfo[] recipients)
recipients - - a collection of per-recipient informationpublic void setUnauthenticatedAttributes(Attribute[] attributes)
attributes - the unauthenticated attributes to be setpublic javax.crypto.SecretKey setupMac(java.security.Key recipientKey,
int recipientInfoIndex)
throws java.security.InvalidKeyException,
java.security.NoSuchAlgorithmException,
CMSException
This method first uses the given key for decrypting the encrypted temporary symmetric key obtained from the corresponding RecipientInfo structure, and subsequently uses this MAC key to initialize the MAC calculation. The MAC calculation actually is done during reading the data obtained by calling method getInputStream. So do not call method getInputStream before setting up the MAC engine or behind verifying the MAC, e.g.:
// the input stream supplying the BER encoded AuthenticatedData
InputStream encodedStream = ...;
// parse the AuthenticatedData
AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);
if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
InputStream contentIs = ...; // the content supplied from an input stream
authenticatedData.setInputStream(contentIs);
}
// the index into the recipientInfos field
int recipientIndex = ...;
// the corresponding recipient key
Key recipientKey = ...;
// decrypt the encrypted MAC key with the private key of the recipient:
autenticatedData.setupMac(recipientKey, recipientIndex);
InputStream contentIs = authenticatedData.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
// 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!");
Note that you have to know the right index into the recipientInfos field when
using this method for setting up the MAC calculation. You may search for the index by
using one of the getRecipientInfo methods thereby identifying the recipient by its
keyIdentifier or -- if suitable for the key management algorithm used -- certificate.
However, when having some recipient using a key agreement protocol the corresponding RecipientInfo is of type KeyAgreeRecipientInfo which may hold encrypted MAC keys for more than only one recipients using the same key agreement algorithm with same domain parameters. Since this setupMac method only can get the KeyAgreeRecipientInfo with the given index (but not search for the right recipient in the KeyAgreeRecipientInfo), it will step through any recipient included in the KeyAgreeRecipientInfo trying to decrypt the encrypted MAC key with the supplied key. This may give some overhead; so it might be appropriate to use another setupMac method allowing to immediately identify the particular recipient in mind by its #setupMac(Key, KeyIdentifier) keyIdentifier} or certificate.
recipientKey - - the key of the recipient to be used for decrypting the encrypted mac key.recipientInfoIndex - - the index into the recipientInfos fieldCMSException - - if there occurs an error while decrypting the mac key or setting
up the mac calculation, or no RecipientInfo for the requested recipient is includedjava.security.NoSuchAlgorithmException - - if there is no implementation of the mac algorithmjava.security.InvalidKeyException - - if the specified key is not validpublic javax.crypto.SecretKey setupMac(java.security.Key recipientKey,
KeyIdentifier recipientIdentifier)
throws java.security.InvalidKeyException,
java.security.NoSuchAlgorithmException,
CMSException
// the input stream supplying the BER encoded AuthenticatedData
InputStream encodedStream = ...;
// parse the AuthenticatedData
AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);
if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
InputStream contentIs = ...; // the content supplied from an input stream
authenticatedData.setInputStream(contentIs);
}
// the KeyIdentifier identifying the recipient key
KeyIdentifier recipientIdentifier = ...;
// the corresponding recipient key
Key recipientKey = ...;
// decrypt the encrypted MAC key with the private key of the recipient:
autenticatedData.setupMac(recipientKey, recipientIdentifier);
InputStream contentIs = authenticatedData.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
// 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!");
This setupMac method can be used to setup the MAC engine any type of RecipientInfo. The supplied
recipient identifier will be used for searching for the right RecipientInfo in the
recipientInfos field.recipientKey - - the key of the recipient to be used for decrypting the encrypted mac key.recipientIdentifier - - specifies which RecipientInfo the given key belongs tojava.security.InvalidKeyExceptionjava.security.NoSuchAlgorithmExceptionCMSExceptionpublic javax.crypto.SecretKey setupMac(java.security.Key recipientKey,
X509Certificate recipientCertificate)
throws java.security.InvalidKeyException,
java.security.NoSuchAlgorithmException,
CMSException
This method first uses the given key for decrypting the encrypted temporary symmetric key obtained from the corresponding RecipientInfo structure, and subsequently uses this MAC key to initialize the mac calculation. The MAC calculation actually is done during reading the data obtained by calling method getInputStream. So do not call method getInputStream() before setting up the mac engine or behind verifying the mac, e.g.:
// the input stream supplying the BER encoded AuthenticatedData
InputStream encodedStream = ...;
// parse the AuthenticatedData
AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);
if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
InputStream contentIs = ...; // the content supplied from an input stream
authenticatedData.setInputStream(contentIs);
}
// the recipient certificate:
X509Certificate recipientCert = ...;
// the corresponding private key
PrivateKey recipientPrivateKey = ...;
// setup the MAC by decrypting the secret MAC key
autenticatedData.setupMac(recipientPrivateKey, recipientCert);
InputStream contentIs = authenticatedData.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
// 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!");
This setupMac method can be used to setup the MAC engine any type of RecipientInfo. The supplied
recipient identifier will be used for searching for the right RecipientInfo in the
recipientInfos field.recipientKey - - the key of the recipient to be used for decrypting the encrypted mac key.recipientCertificate - - specifies which RecipientInfo the given key belongs tojava.security.InvalidKeyExceptionjava.security.NoSuchAlgorithmExceptionCMSExceptionpublic void setupMac(javax.crypto.SecretKey macKey)
throws java.security.InvalidKeyException,
java.security.NoSuchAlgorithmException,
CMSException
The secret key supplied to this method has to be the already decrypted MAC key.
The MAC calculation actually is done during reading the data obtained by calling method getInputStream. So do not call method getInputStream before setting up the mac engine or behind verifying the mac, e.g.:
// the input stream supplying the BER encoded AuthenticatedData
InputStream encodedStream = ...;
// parse the AuthenticatedData
AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);
if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
InputStream contentIs = ...; // the content supplied from an input stream
authenticatedData.setInputStream(contentIs);
}
//the MAC key
Key macKey = ...;
// setup the MAC engine
autenticatedData.setupMac(macKey);
InputStream contentIs = authenticatedData.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
// 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!");macKey - the temporary symmetric key that has been used to calculate the message
authentication codejava.security.InvalidKeyExceptionjava.security.NoSuchAlgorithmExceptionCMSExceptionpublic ASN1Object toASN1Object() throws CMSException
toASN1Object in interface ContentStreamCMSException - if the ASN1Object could not be createdprotected ASN1Object toASN1Object(int blockSize) throws CMSException
blockSize - the block size defining the encoding scheme - and specifying
the length of each primitive encoded octet string component,
if positiveCMSException - if the ASN1Object could not be createdpublic java.lang.String toString()
toString in class java.lang.Objectpublic java.lang.String toString(boolean detailed)
DigestedData object.toString in interface ContentStreamdetailed - whether or not to give detailed information about the implemented
CMS content type.public boolean verifyMac()
throws CMSException
// the input stream supplying the BER encoded AuthenticatedData
InputStream encodedStream = ...;
// parse the AuthenticatedData
AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);
if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) {
// in explicit mode explicitly supply the content for hash/mac computation
InputStream contentIs = ...; // the content supplied from an input stream
authenticatedData.setInputStream(contentIs);
}
// the recipient certificate:
X509Certificate recipientCert = ...;
// the corresponding private key
PrivateKey recipientPrivateKey = ...;
// setup the MAC by decrypting the secret MAC key
autenticatedData.setupMac(recipientPrivateKey, recipientCert);
InputStream contentIs = authenticatedData.getInputStream();
byte[] buf = new byte[1024];
int r;
while ((r = data_is.read(buf)) > 0) {
// do something useful
}
// 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!");CMSMacException - - if the MAC verification process fails for some reason
(e.g. the authenticated attributes (if incldued) cannot be parsed or the content
hash does not match to value of the included MessageDigest attribute)CMSExceptionpublic byte[] getAuthenticatedDigest()
throws CMSException
CMSExceptionpublic void writeTo(java.io.OutputStream os)
throws java.io.IOException
os - the output stream to which this DigestedData shall be writtenjava.io.IOException - if an IOException occurs while writing to the streampublic void writeTo(java.io.OutputStream os,
int blockSize)
throws java.io.IOException
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>
os - the output stream to which this DigestedData shall be writtenblockSize - the block size defining the encoding scheme - and specifying
the length of each primitive encoded octet string component,
if positivejava.io.IOException - if an error occurs during writing the object