|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object iaik.cms.AuthenticatedDataStream
public class AuthenticatedDataStream
This class represents the stream-supporting implementation of 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 AuthenticatedDataStream
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 = AuthenticatedDataStream.IMPLICIT; // include contentor
int mode = AuthenticatedDataStream.EXPLICIT; // do not include contentHowever, in both cases the content data has to be supplied when creating the
AuthenticatedDataStream
object, because it is needed for the
MAC computation:
InputSrteam[] dataStream = ...; // the content data supplying input streamTogether with transmission mode and content data the following values have to be specified when creating an AuthenticatedDataStream 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 supplying input stream: InputStream dataStream = ...; // the mac algorithm to be used AlgorithmID macAlgorithm = (AlgorithmID)AlgorithmID.hMAC_SHA512.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.sha512.clone(); // the transmission mode (either AuthenticatedDataStream.IMPLICIT or AuthenticatedDataStream.EXPLICIT) int mode = ...; // create the AuthenticatedDataStream object: AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(contentType, dataStream, 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 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).
If the content shall not be included in the AuthenticatedData object (EXPLICIT
mode) now it is time to read away the content to transmit it by other means.
While reading the content from the stream it is piped through a InputStreamHashEngine
(since authenticated attributes
are present) to calculate and set the value of the MessageDigest
attribute. Later, during the encoding procedure (when calling method
writeTo
) the mac value is calculated from the DER encoded
authenticated attributes (if no authenticated attributes are set, an InputStreamMacEngine
is used to immediately calculate
the mac value from the content data), e.g.:
// in explicit mode get the content and write it to any out-of-band place if (mode == AuthenticatedDataStream.EXPLICIT) { InputStream contentIs = authenticatedData.getInputStream(); byte[] buf = new byte[2048]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful } }Finally method
writeTo
has to be called for BER encoding
the AuthenticatedDataStream object and writing it to an output stream. It is recommended
to specify a positive block size value for splitting the data encoding:
int blockSize = ...; authenticatedData.writeTo(output_stream, blockSize);respectively
authenticatedData.writeTo(output_stream);It is recommended only to use the
writeTo
method where a particular
block size can be specified, because it is the intended purpose of this stream-supporting
AuthenticatedData implementation to handle large amounts of data. When no block size is
specified the whole content data is encoded as one primitive definite octet string, which
advantageously may be done when using the non-stream supporting AuthenticatedData
implementation.
When a positive block size is specified for encoding the AuthenticatedData to a stream,
the content data is BER encoded as indefinite constructed octet string being composed
of a series of definite primitive encoded octet strings of blockSize
length,
e.g. (for some small data):
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
.
When receiving an AuthenticatedData message use the AuthenticatedDataStream(InputStream)
constructor for parsing the AuthenticatedData
from its BER encoding:
// the input stream supplying the BER encoded AuthenticatedData InputStream encodedStream = ...; // parse the AuthenticatedData AuthenticatedDataStream authenticatedData = new AuthenticatedDataStream(encodedStream);If the content has been transmitted by other means (
EXPLICIT
mode) it
now has to be supplied by calling method setInputStream
since it is required for MAC computation (verification):
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); }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 the recipients have
used the Static-Static DH key agreement
technique,
the recipient private key is required derive the key encryption key which subsequently
is used 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 data can be obtained and read to calculate and subsequently verify the MAC value:
InputStream contentIs = authenticatedData.getInputStream(); byte[] buf = new byte[2048]; 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 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
,
KeyAgreeRecipientInfo
Field Summary | |
---|---|
static int |
EXPLICIT
Denotes a mode where the content is not transmitted within the AuthenticatedData. |
static int |
IMPLICIT
Denotes a mode where the content is included in the AuthenticatedData. |
Constructor Summary | |
---|---|
protected |
AuthenticatedDataStream()
Default constructor for dynamic object creation. |
|
AuthenticatedDataStream(java.io.InputStream is)
Creates an AuthenticatedDataStream from a BER encoded AutheticatedData object which is read from the given InputStream. |
|
AuthenticatedDataStream(java.io.InputStream is,
SecurityProvider securityProvider)
Creates an AuthenticatedDataStream from a BER encoded AutheticatedData object which is read from the given InputStream. |
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream is,
AlgorithmID macAlg,
byte[] mac,
AlgorithmID digestAlg,
int mode)
Creates an AuthenticatedDataStream from an already calculated MAC value. |
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream is,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
AlgorithmID digestAlg,
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 is,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
AlgorithmID digestAlg,
int mode,
SecurityProvider securityProvider)
Creates a new AuthenticatedDataStream where the to-be-authenticated content data is supplied by an input stream. |
|
AuthenticatedDataStream(ObjectID contentType,
java.io.InputStream is,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
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 is,
AlgorithmID macAlg,
int macKeyLength,
java.security.spec.AlgorithmParameterSpec macParams,
int mode,
SecurityProvider securityProvider)
Creates a new AuthenticatedDataStream where the to-be-authenticated content data is supplied by an input stream. |
Method Summary | |
---|---|
void |
addRecipientInfo(RecipientInfo recipient)
Adds one recipient to the list of recipient infos. |
void |
decode(java.io.InputStream is)
Reads and decodes a BER encoded AutheticatedData from a the given input stream. |
void |
encodeCalled(ASN1Object obj,
int id)
This method implements the EncodeListener interface. |
Attribute |
getAuthenticatedAttribute(ObjectID oid)
Returns the first authenticated attribute matching to the given ObjectID, if included in this AutheticatedData object. |
Attribute[] |
getAuthenticatedAttributes()
Gets the authenticated attributes included in this AutheticatedData. |
byte[] |
getAuthenticatedDigest()
Gets the value of the MessageDigest attribute, if 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()
Gets the digest algorithm, if set. |
ObjectID |
getEncapsulatedContentType()
Returns the content type the inherent EncapsulatetContentInfo represents. |
java.io.InputStream |
getInputStream()
Returns an InputStream from where the content data can be read. |
byte[] |
getMac()
Gets the MAC value. |
AlgorithmID |
getMacAlgorithm()
Gets the MAC algorithm. |
int |
getMode()
Returns the mode of this AuthenticatedData. |
OriginatorInfo |
getOriginatorInfo()
Gets the OriginatorInfo, if included. |
RecipientInfo |
getRecipientInfo(KeyIdentifier recipientIdentifier)
Returns the RecipientInfo belonging to the recipient identified by the given recipient identifier. |
RecipientInfo |
getRecipientInfo(X509Certificate recipientCertificate)
Returns the recipient info matching to the supplied recipient certificate. |
RecipientInfo[] |
getRecipientInfos()
Returns all the recipient infos included in this AutheticatedData object. |
RecipientInfo[] |
getRecipientInfos(int type)
Returns all the recipient infos included in this AutheticatedData object that have the specified type. |
SecurityProvider |
getSecurityProvider()
Gets the SecurityProvider installed for this AuthenticatedDataStream. |
Attribute |
getUnauthenticatedAttribute(ObjectID oid)
Returns the first unauthenticated attribute matching to the given ObjectID, if included in this AutheticatedData object. |
Attribute[] |
getUnauthenticatedAttributes()
Gets the unauthenticated attributes included in this AutheticatedData. |
int |
getVersion()
Returns the syntax version number. |
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. |
void |
setSecurityProvider(SecurityProvider securityProvider)
Sets the SecurityProvider for this AuthenticatedDataStream. |
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 setup 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 certificate. |
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 AuthenticatedDataStream as ASN1Object. |
protected ASN1Object |
toASN1Object(int blockSize)
Returns this AutheticatedData as ASN1Object. |
java.lang.String |
toString()
Returns a string giving some information about this AutheticatedData object. |
java.lang.String |
toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this AutheticatedData object. |
boolean |
verifyMac()
Verifies the message authentication code. |
void |
writeTo(java.io.OutputStream os)
BER encodes this AutheticatedData and writes the encoding to the supplied output stream. |
void |
writeTo(java.io.OutputStream os,
int blockSize)
Writes the BER encoding of this AutheticatedData to the supplied output stream where a constructed OCTET STRING may be used for encoding the content. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
public static final int IMPLICIT
public static final int EXPLICIT
Constructor Detail |
---|
protected AuthenticatedDataStream()
public AuthenticatedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, int mode) throws java.security.NoSuchAlgorithmException
InputStreamMacEngine
to wrap a mac calculating input stream around
the data supplying input stream.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)is
- an input stream suppliyng 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, int mode, SecurityProvider securityProvider) throws java.security.NoSuchAlgorithmException
InputStreamMacEngine
to wrap a mac calculating input stream around
the data supplying input stream.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)is
- an input stream suppliyng 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, AlgorithmID digestAlg, int mode) throws java.security.NoSuchAlgorithmException
digestAlg
parameter
is not null, an InputStreamHashEngine
is used to wrap a hash calculating input stream around the data supplying
input stream. In this case authenticated attributes have to be set
by calling method setAuthenticatedAttributes
and the MAC value is 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, an InputStreamMacEngine
to wrap a MAC calculating
input stream around the data supplying input stream for calculating the MAC
value immediately from the content.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)is
- an input stream supplying 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID macAlg, int macKeyLength, java.security.spec.AlgorithmParameterSpec macParams, AlgorithmID digestAlg, int mode, SecurityProvider securityProvider) throws java.security.NoSuchAlgorithmException
digestAlg
parameter
is not null, an InputStreamHashEngine
is used to wrap a hash calculating input stream around the data supplying
input stream. In this case authenticated attributes have to be set
by calling method setAuthenticatedAttributes
and the MAC value is 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, an InputStreamMacEngine
to wrap a MAC calculating
input stream around the data supplying input stream for calculating the MAC
value immediately from the content.
contentType
- the type of the authenticated content (e.g. ObjectID.cms_data)is
- an input stream suppliyng 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 AuthenticatedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID macAlg, byte[] mac, AlgorithmID digestAlg, int mode)
setAuthenticatedAttributes
are supplied, they already have to contain
the MessageDigest attribute. Any RecipientInfo
added
to this AuthenticatedDataStream 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)is
- an input stream suppliyng 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 meanspublic AuthenticatedDataStream(java.io.InputStream is) throws CMSParsingException, java.io.IOException
is
- the InputStream supplying a BER 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 AuthenticatedDataStream(java.io.InputStream is, SecurityProvider securityProvider) throws CMSParsingException, java.io.IOException
is
- the InputStream supplying a BER 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 setSecurityProvider(SecurityProvider securityProvider)
This method allows to explicitly set a SecurityProvider for this AuthenticatedDataStream. If no explicit SecurityProvider is set, the default system wide installed SecurityProvider will be used for the required cryptographic operations.
This class uses the following method(s) of the SecurityProvider
, which may be overriden by an application, if required:
getInputStreamHashEngine
methods to get an InputStreamHashEngine
for stream based digest calculation
getInputStreamMacEngine
methods to get an InputStreamMacEngine
for stream based mac calculation
calculateMac
for mac calculation from DER encoded authenticated attributes; if present
generateKey
to generate the symmetric mac key
getAlgorithmParameterSpec
to create an AlgorithmParameterSpec from algorithm parameters (if included in a MAC
algorithmID)
securityProvider
- the SecurityProvider to be setpublic SecurityProvider getSecurityProvider()
This class uses the following method(s) of the SecurityProvider
, which may be overriden by an application, if required:
getInputStreamHashEngine
methods to get an InputStreamHashEngine
for stream based digest calculation
getInputStreamMacEngine
methods to get an InputStreamMacEngine
for stream based mac calculation
calculateMac
for mac calculation from DER encoded authenticated attributes; if present
generateKey
to generate the symmetric mac key
getAlgorithmParameterSpec
to create an AlgorithmParameterSpec from algorithm parameters (if included in a MAC
algorithmID)
set
for this object,
the default system wide installed SecurityProvider will be used for the required cryptographic
operations. However, this method will return null
if it does not have its own
SecurityProvider.
null
if
this object does not have its own SecurityProviderpublic void decode(java.io.InputStream is) throws java.io.IOException, CMSParsingException
decode
in interface ContentStream
is
- the InputStream holding a BER 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 ObjectID getContentType()
Use method getEncapsulatedContentType
for getting the type of the inherent (authenticated) content.
getContentType
in interface ContentStream
ObjectID.cms_autheticatedData
public ObjectID getEncapsulatedContentType()
public void setOriginatorInfo(OriginatorInfo originatorInfo)
The originatorInfo may be set for including certificates and/or certificate revocation lists for the originator if required by the key management algorithm used.
originatorInfo
- the OriginatorInfo to be setpublic void setRecipientInfos(RecipientInfo[] recipients)
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.
recipients
- a collection of per-recipient informationRecipientInfo
,
KeyTransRecipientInfo
,
KeyAgreeRecipientInfo
,
KEKRecipientInfo
,
PasswordRecipientInfo
,
OtherRecipientInfo
public void addRecipientInfo(RecipientInfo recipient)
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.
recipient
- the RecipientInfo to be addedRecipientInfo
,
KeyTransRecipientInfo
,
KeyAgreeRecipientInfo
,
KEKRecipientInfo
,
PasswordRecipientInfo
,
OtherRecipientInfo
public void setAuthenticatedAttributes(Attribute[] attributes)
digestAlgorithm
field is not allowed to be null since it identifies the algorithm to
be used for calculating a digest value from the content and set it
as MessageDigest attribute. If the MessageDigest attribute is not
included in the set of attributes supplied to this methode, it
is automatically calculated and set.
attributes
- the authenticated attributes to be set
java.lang.NullPointerException
- if no digest algorithm has been specified
when creating this AuthenticatedDataStream objectpublic void setUnauthenticatedAttributes(Attribute[] attributes)
attributes
- the unauthenticated attributes to be setpublic void setBlockSize(int blockSize)
blockSize
is smaller or equal to zero the
whole content data is encoded as definite primitive octet string, otherwise
indefinite constructed encoding is used.
setBlockSize
in interface ContentStream
blockSize
- for defining the encoding scheme and setting the octet
string component length, if positivepublic int getBlockSize()
blockSize
is smaller or equal to zero the
whole data is encoded as definite primitive octet string, otherwise
indefinite constructed encoding is used.
getBlockSize
in interface ContentStream
public javax.crypto.SecretKey setupMac(java.security.Key recipientKey, int recipientInfoIndex) throws CMSException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
recipientInfoIndex
.
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[2048]; 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 field
CMSException
- if there occurs an error while decrypting the mac key
or setting up the mac calculation, or no RecipientInfo
for the requested recipient is included
java.security.NoSuchAlgorithmException
- if there is no implementation of the mac algorithm
java.security.InvalidKeyException
- if the specified key is not validpublic javax.crypto.SecretKey setupMac(java.security.Key recipientKey, KeyIdentifier recipientIdentifier) throws CMSException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
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 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[2048]; 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 to
CMSException
- if there occurs an error while decrypting the mac key
or setting up the mac calculation, or no RecipientInfo
for the requested recipient is included
java.security.NoSuchAlgorithmException
- if there is no implementation of the mac algorithm
java.security.InvalidKeyException
- if the specified key is not validpublic javax.crypto.SecretKey setupMac(java.security.Key recipientKey, X509Certificate recipientCertificate) throws CMSException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
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[2048]; 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 this method only can be used for decrypting the encrypted mac key
if the recipient in mind has a RecipientInfo of type KeyTransRecipientInfo
or KeyAgreeRecipientInfo
using a public
key from a certificate for its key management protocol.
recipientKey
- the private key of the recipient to be used for decrypting
the encrypted mac key.recipientCertificate
- the certificate of the recipient specifying which
RecipientInfo the recipient private key belongs to
CMSException
- if there occurs an error while decrypting the mac key
or setting up the mac calculation, or no RecipientInfo
for the requested recipient is included
java.security.NoSuchAlgorithmException
- if there is no implementation of the mac algorithm
java.security.InvalidKeyException
- if the specified key is not validpublic void setupMac(javax.crypto.SecretKey macKey) throws CMSException, java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
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 may key Key macKey = ...; // setup the MAC engine autenticatedData.setupMac(macKey); InputStream contentIs = authenticatedData.getInputStream(); byte[] buf = new byte[2048]; 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 code
CMSException
- if there occurs an error when setting up the mac calculation,
or no RecipientInfo for the requested recipient is included
java.security.NoSuchAlgorithmException
- if there is no implementation of the mac algorithm
java.security.InvalidKeyException
- if the specified key is not validpublic byte[] getAuthenticatedDigest() throws CMSException
CMSException
- if no message digest attribute is includedpublic int getMode()
IMPLICIT
or EXPLICIT
public boolean verifyMac() throws CMSMacException
For verifying the MAC value first the mac calcualtion has to be set up
by calling a proper setupMac
method and the content data
has to be get
and entirely read:
// 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[2048]; 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!");
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 java.io.InputStream getInputStream()
Attention! The stream only may be read once.
When having created a new AuthenticatedDataStream
object to
be encoded to a stream, this method should only be called in EXPLICT
mode to get and read away the content to be transmitted by other means.
When having decoded and parsed a received AuthenticatedDataStream
object
coming from some stream, this method may be used for obtaining the raw (decrypted) data
after having setup the mac engine for mac calculation/verifation, 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); } // setup the mac calculation autenticatedData.setupMac(...); // get and read the content data InputStream contentIs = authenticatedData.getInputStream(); byte[] buf = new byte[2048]; 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!");
public void setInputStream(java.io.InputStream is)
AuthenticatedDataStream
object to
be encoded to a stream, this method may be used to supply the content
to be authenticated.
AuthenticatedDataStream
object
coming from some stream, this method may be used for supplying the
content transmitted by other means (EXPLICIT mode).
is
- the input stream holding the content data to be authenticatedpublic int getVersion()
public OriginatorInfo getOriginatorInfo()
The originatorInfo may be set for including certificates and/or certificate revocation lists if required by the key management algorithm used.
null
public RecipientInfo[] getRecipientInfos()
AutheticatedData
object.
RecipientInfo
objects
included into this AutheticatedData
public RecipientInfo[] getRecipientInfos(int type)
AutheticatedData
object that have the specified type.
RecipientInfo
objects
included into this AutheticatedData
that have the
specified type (e.g. all KeyTransRecipientInfos); the array may
be empty if no RecipientInfo with the requested type is includedpublic RecipientInfo getRecipientInfo(X509Certificate recipientCertificate)
This method may be used by a recipient for quering for the recipient info
that holds the mac key encrypted with the public key of the
given certificate.
Note that this method only can be used for searching for RecipientInfos
of type KeyTransRecipientInfo
or
KeyAgreeRecipientInfo
, but NOT
for a RecipientInfo of type KEKRecipientInfo
or PasswordRecipientInfo
which does use a certificate.
null
if no recipient info belonging to the given
certificate can be foundpublic RecipientInfo getRecipientInfo(KeyIdentifier recipientIdentifier)
recipientIdentifier
- the recipient identifier identifying the
recipient in mind
null
if no recipient info belonging to the given
recipient identifier can be foundpublic AlgorithmID getMacAlgorithm()
public AlgorithmID getDigestAlgorithm()
null
if no digest algorithm is setpublic Attribute[] getAuthenticatedAttributes()
public Attribute[] getUnauthenticatedAttributes()
public Attribute getAuthenticatedAttribute(ObjectID oid)
null
if there is no attribute for the given OID.public byte[] getMac()
public Attribute getUnauthenticatedAttribute(ObjectID oid)
null
if there is no attribute for the given OID.public ASN1Object toASN1Object() throws CMSException
writeTo
is called).
toASN1Object
in interface ContentStream
AuthenticatedDataStream
as ASN1Object.
CMSException
- if the ASN1Object could not be createdprotected ASN1Object toASN1Object(int blockSize) throws CMSException
If
The ASN.1 SEQUENCE returned by this method only will contain the first
components (version, (originatorInfo), recipientInfos, macAlgorithm,
(digestAlgorithm) and EncapsulatedContentInfo without content) of the ASN.1
AuthenticatedData. The remaining components (autenticated attributes, mac value
autenticated attributes) are added later during the encoding procedure
(when
writeTo
is called).
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 could not be created
public void encodeCalled(ASN1Object obj, int id) throws CodingException
AuthenticatedDataStream
registers itself as encode listener
for the SEQUENCE representing the final ASN.1 AuthenticatedData object. After
the content stram has been read and before attributes and mac value
are to be encoded, this class is notified by means of the
IAIK-JCE EncodeListener
utility.
This method shall not be called by an application!
encodeCalled
in interface EncodeListener
obj
- the SignedData SEQUENCEid
- the id identifying the SEQUENCE to be processed
CodingException
- if an error occurs when computing/signing
the message digestpublic void writeTo(java.io.OutputStream os) throws java.io.IOException
os
- the output stream to which this AutheticatedData shall be written
java.io.IOException
public void writeTo(java.io.OutputStream os, int blockSize) throws java.io.IOException
If the a positive blockSize
value is specified, the content
is encoded as indefinite constructed octet string being composed of a certain number
of definite primitive encoded octet strings of blockSize
length:
0x24 0x80 0x04 <blocksize> <first encrypted content block> 0x04 <blocksize> <second encrypted content block> 0x04 <blocksize> <third encrypted content block> ... 0x00 0x00Otherwise the whole content is encoded as definite primitive octet string:
0x04 <length> <encrypted content>
os
- the output stream to which this AuthenticatedData shall be writtenblockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if positive
java.io.IOException
- if an error occurs during writing the objectpublic void notifyEOF() throws java.io.IOException
iaik.utils.NotifyEOFInputStream
is wrapped around this content data stream
for indicating that the parsing procedure is to be notified when the stream actually
has been read. At that point, the programm exceuting automatically jumps to the
notifyEOF
method for finishing the decoding by parsing the
remaining authenticated and unauthenticated attributes, if present, and the mac value.
notifyEOF
in interface EOFListener
java.io.IOException
- if an error occurs while parsing the streampublic java.lang.String toString()
AutheticatedData
object.
toString
in class java.lang.Object
public java.lang.String toString(boolean detailed)
AutheticatedData
object.
toString
in interface ContentStream
detailed
- - whether or not to give detailed information
|
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 |