|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object iaik.cms.AuthenticatedDataStream iaik.cms.AuthenticatedData
public class AuthenticatedData
This class implements the CMS content type AutheticatedData
.
Each CMS content type is associated with a specific object identifier.
The object identifier for the AutheticatedData
content type is
defined as:
id-ct-authData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
us(840) rsadsi(113549) pkcs(1) 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 AutheticatedData
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 commonly at random 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 AuthenticedData message.
The AutheticatedData
type is defined as ASN.1 SEQUENCE type
containing the following components (see
RFC 5652):
AuthenticatedData ::= SEQUENCE { version CMSVersion, 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 AutheticatedData
message,
decrypts the corresponding encrypted mac key with his/her key and
subsequently uses it to verify the message authentication code.
See RFC 5652 for more information.
When creating
an AuthenticatedData
object an application has to decide whether the to-be-authenticated content
shall be included (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_SHA256.clone(); // the length of the mac key to be generated int macKeyLength = 32; // 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.sha256.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 (EC)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 one RecipientInfo (containing recipient information for the sender
who wants to be able to verify the MAC, too, and one for the final recipient). To provide
origin authentication we use Static-Static ECDH with dhSinglePass-stdDH-sha256kdf-scheme
as key management technique together with AES256-Wrap (RFC 3394) for encrypting (wrapping)
the HMAC key:
// the key encryption (key agreement) algorithm to use: AlgorithmID keyEA = (AlgorithmID)CMSAlgorithmID.dhSinglePass_stdDH_sha256kdf_scheme.clone(); // the key wrap algorithm to use: AlgorithmID keyWrapAlg = (AlgorithmID)AlgorithmID.cms_aes256_wrap.clone(); // the length of the key encryption key to be generated: int kekLength = 256; // in static-static mode we supply user keying material so that a different kek is generated SecureRandom random = ...; byte[] ukm = new byte[64]; random.nextBytes(ukm); RecipientInfo[] recipients = new RecipientInfo[1]; recipients[0] = new KeyAgreeRecipientInfo(originatorCert, originatorPrivateKey, KeyIdentifier.ISSUER_AND_SERIALNUMBER, keyEA, keyWrapAlg, kekLength, ukm); // add originator) as recipient, too ((KeyAgreeRecipientInfo)recipients[0]).addRecipient(originatorCert, CertificateIdentifier.ISSUER_AND_SERIALNUMBER); // add the final recipient (cert identified by RecipientKeyIdentifier for demonstration purposes) ((KeyAgreeRecipientInfo)recipients[0]).addRecipient(recipientCert, CertificateIdentifier.RECIPIENT_KEY_IDENTIFIER); // set the recipients of the authenticated message authenticatedData.setRecipientInfos(recipients);Note that when using static-static DH the message should not be sent to more than only one final recipient (except for the sender) (see RFC 6278).
Finally the AuthenticatedData object has to be prepared for transmission by transforming
it into an ASN1Object or immediately 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 0x00instead of:
0x04 0x05 0x01 0xAB 0x23 0x7F 0xCAfor encoding the five data bytes
0x01 0xAB 0x23 0x7F 0xCA
. Of course, this only
might be useful when having to handle big amounts of data.
When receiving an AuthenticatedData message use the AuthenticatedData(InputStream)
constructor for parsing the AuthenticatedData
from its BER encoding:
// the input stream supplying the 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 agreement
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();Note that the example above uses Elliptic Curve DH. For that reason you would not only need
iaik_cms.jar
and iaik_jce_(full).jar
(IAIK-JCE,
https://jce.iaik.tugraz.at/products/core-crypto-toolkits/jca-jce/) in your classpath,
but also iaik_eccelarate.jar
(IAIK-ECCelerateTM,
https://jce.iaik.tugraz.at/products/core-crypto-toolkits/eccelerate/).
RecipientInfo
,
KeyTransRecipientInfo
Field Summary |
---|
Fields inherited from class iaik.cms.AuthenticatedDataStream |
---|
EXPLICIT, IMPLICIT |
Constructor Summary | |
---|---|
protected |
AuthenticatedData()
Default constructor for dynamic object creation in ContentInfoStream. |
|
AuthenticatedData(java.io.InputStream is)
Creates an AuthenticatedData from an encoded AutheticatedData object which is read from the given InputStream. |
|
AuthenticatedData(java.io.InputStream is,
SecurityProvider securityProvider)
Creates an AuthenticatedData from an encoded AutheticatedData object which is read from the given InputStream. |
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlg,
byte[] mac,
AlgorithmID digestAlg,
int mode)
Creates an AuthenticatedData from an already calculated MAC value. |
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
AlgorithmID digestAlg,
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 macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
AlgorithmID digestAlg,
int mode,
SecurityProvider securityProvider)
Creates a new AuthenticatedData where the to-be-authenticated content data is supplied from an byte array. |
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlg,
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. |
|
AuthenticatedData(ObjectID contentType,
byte[] content,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
int mode,
SecurityProvider securityProvider)
Creates a new AuthenticatedData where the to-be-authenticated content data is supplied from an byte array. |
Method Summary | |
---|---|
void |
decode(ASN1Object obj)
Reads and parses an AutheticatedData from the given ASN.1 representation. |
void |
decode(java.io.InputStream is)
Reads and decodes an encoded AutheticatedData from the given input stream. |
byte[] |
getContent()
Returns the content. |
byte[] |
getEncoded()
Returns the BER encoding of this AuthenticatedData object as byte array. |
java.io.InputStream |
getInputStream()
Returns an InputStream from where the content data 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. |
void |
setupMac(javax.crypto.SecretKey macKey)
Uses the given symmetric mac key to setup the mac calculation to verify the message authentication code when parsing an AuthenticatedData object . |
protected ASN1Object |
toASN1Object(int blockSize)
Returns this AutheticatedData as ASN1Object. |
boolean |
verifyMac()
Verifies the message authentication code. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Methods inherited from interface iaik.cms.ContentStream |
---|
getBlockSize, getContentType, setBlockSize, toASN1Object, toString |
Constructor Detail |
---|
protected AuthenticatedData()
public AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, int mode) throws java.security.NoSuchAlgorithmException
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)content
- the to-be-authenticated datamacAlg
- 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 IaikProvider
tries to determine the block length
of the mac algorithm in use; otherwise it uses the
length of the underlying digest algorithm.macParams
- any parameters, if required by the mac algorithmmode
- the transmission mode; either IMPLICIT
(to include
the content) or EXPLICIT
to transmit it by other means
java.security.NoSuchAlgorithmException
- if the requested digest or mac algorithm is not
supported or the MAC key cannot be createdpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, int mode, SecurityProvider securityProvider) throws java.security.NoSuchAlgorithmException
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)content
- the to-be-authenticated datamacAlg
- 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 IaikProvider
tries to determine the block length
of the mac algorithm in use; otherwise it uses the
length of the underlying digest algorithm.macParams
- any parameters, if required by the mac algorithmmode
- the transmission mode; either IMPLICIT
(to include
the content) or EXPLICIT
to transmit it by other meanssecurityProvider
- the SecurityProvider to be used for any required
cryptographic operation
java.security.NoSuchAlgorithmException
- if the requested digest or mac algorithm is not
supported or the MAC key cannot be createdpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, AlgorithmID digestAlg, int mode) throws java.security.NoSuchAlgorithmException
digestAlg
parameter
is not null authenticated attributes have to be set by calling method
setAuthenticatedAttributes
and the MAC value will be calculated from the DER encoded authenticated attributes
which have to contain the -- (if not set) automatically calculated -- MessageDigest
attribute.
However, if the digestAlg
parameter is null, the MAC
value will be computed immediately from the content.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)content
- the to-be-authenticated datamacAlg
- 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 IaikProvider
tries to determine the block length
of the mac algorithm in use; otherwise it uses the
length of the underlying digest algorithm.macParams
- any parameters, if required by the mac algorithmdigestAlg
- 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 means
java.security.NoSuchAlgorithmException
- if the requested digest or mac algorithm is not
supported or the MAC key cannot be createdpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, AlgorithmID digestAlg, int mode, SecurityProvider securityProvider) throws java.security.NoSuchAlgorithmException
digestAlg
parameter
is not null authenticated attributes have to be set by calling method
setAuthenticatedAttributes
and the MAC value will be calculated from the DER encoded authenticated attributes
which have to contain the -- (if not set) automatically calculated -- MessageDigest
attribute.
However, if the digestAlg
parameter is null, the MAC
value will be computed immediately from the content.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)content
- the to-be-authenticated datamacAlg
- 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 IaikProvider
tries to determine the block length
of the mac algorithm in use; otherwise it uses the
length of the underlying digest algorithm.macParams
- any parameters, if required by the mac algorithmdigestAlg
- 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 meanssecurityProvider
- the SecurityProvider to be used for any required
cryptographic operation
java.security.NoSuchAlgorithmException
- if the requested digest or mac algorithm is not
supported or the MAC key cannot be createdpublic AuthenticatedData(ObjectID contentType, byte[] content, AlgorithmID macAlg, byte[] mac, AlgorithmID digestAlg, int mode) throws java.security.NoSuchAlgorithmException
setAuthenticatedAttributes
are supplied, they already have to contain
the MessageDigest attribute. Any RecipientInfo
added
to this AuthenticatedData object already has to contain the encrypted mac key
(i.e. no MAC key is generated and encrypted for each recipient).
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)content
- the to-be-authenticated datamacAlg
- the OID of the MAC algorithm used for mac calculationmac
- the already calculated mac valuedigestAlg
- 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 means
java.security.NoSuchAlgorithmException
public AuthenticatedData(java.io.InputStream is) throws CMSParsingException, java.io.IOException
is
- the InputStream supplying an encoded CMS AutheticatedData object
java.io.IOException
- if an I/O error occurs during reading from the InputStream
CMSParsingException
- if an error occurs while parsing the objectpublic AuthenticatedData(java.io.InputStream is, SecurityProvider securityProvider) throws CMSParsingException, java.io.IOException
is
- the InputStream supplying an encoded CMS AutheticatedData objectsecurityProvider
- the security provider to be used; if null
the
default system-wide SecurityProvider is used
java.io.IOException
- if an I/O error occurs during reading from the InputStream
CMSParsingException
- if an error occurs while parsing the objectMethod Detail |
---|
public void decode(ASN1Object obj) throws CMSParsingException
decode
in interface Content
obj
- the ASN.1 AutheticatedData object
CMSParsingException
- if an error occurs while parsing the ASN.1 objectpublic void decode(java.io.InputStream is) throws java.io.IOException, CMSParsingException
decode
in interface ContentStream
decode
in class AuthenticatedDataStream
is
- the InputStream holding an encoded AutheticatedData object
java.io.IOException
- if an I/O error occurs during reading from the InputStream
CMSParsingException
- if an error occurs while parsing the objectpublic void setupMac(javax.crypto.SecretKey macKey)
The secret key supplied to this method has to be the already decrypted mac key.
The mac calculation actually is done when verifying
the mac, e.g.:
// the input stream supplying the encoded AuthenticatedData InputStream encodedStream = ...; // parse the AuthenticatedData AuthenticatedData authenticatedData = new AuthenticatedData(encodedStream); if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) { // in explicit mode explicitly supply the content for hash/mac computation byte[] content = ...; // the content received by other means authenticatedData.setContent(content); } // supply the may key Key macKey = ...; autenticatedData.setupMac(macKey); // 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!"); // in implicit mode get the content byte[] content = authenticatedData.getContent();
setupMac
in class AuthenticatedDataStream
macKey
- the temporary symmetric key that has been used to calculate the message
authentication codepublic boolean verifyMac() throws CMSMacException
For verifying the MAC value first the mac calcualtion has to be set up
by calling a proper setupMac
method:
// the input stream supplying the encoded AuthenticatedData InputStream encodedStream = ...; // parse the AuthenticatedData AuthenticatedData authenticatedData = new AuthenticatedData(encodedStream); if (authenticatedData.getMode() == AuthenticatedDataStream.EXPLICIT) { // in explicit mode explicitly supply the content for hash/mac computation byte[] content = ...; // the content received by other means authenticatedData.setContent(content); } // the recipient certificate: X509Certificate recipientCert = ...; // the corresponding private key PrivateKey recipientPrivateKey = ...; // setup the MAC by decrypting the secret MAC key autenticatedData.setupMac(recipientPrivateKey, recipientCert); // 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!"); // in implicit mode get the content byte[] content = authenticatedData.getContent();
verifyMac
in class AuthenticatedDataStream
true
if the MAC verifies, false
if not
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)public byte[] getContent()
public java.io.InputStream getInputStream()
getInputStream
in class AuthenticatedDataStream
public void setInputStream(java.io.InputStream is)
setInputStream
in class AuthenticatedDataStream
is
- the input stream holding the content data to authenticatedpublic void setContent(byte[] content)
content
- the content data to authenticatedprotected ASN1Object toASN1Object(int blockSize) throws CMSException
If
toASN1Object
in class AuthenticatedDataStream
blockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if positive
CMSException
- if the ASN1Object cannot not be created
public byte[] getEncoded() throws CMSException
writeTo(OutputStream os, int blockSize)
method
of the parent AuthenticatedDataStream
class.
CMSException
- if an encoding error occurs
|
This Javadoc may contain text parts from text parts from IETF Internet Standard specifications (see copyright note). | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |