public class EncryptedContentInfoStream
extends java.lang.Object
EncryptedContentInfo
type.
The PKCS#7
Cryptographic Message Standard defines the EncryptedContentInfo
type for specifying the content type, the content encryption algorithm
and the encrypted content of an EnvelopedData
,
SignedAndEnvelopedData
, or EncryptedData
structure
(Version 1.5):
EncryptedContentInfo ::= SEQUENCE { contentType ContentType, contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
EncryptedContent ::= OCTET STRING
This class provides several constructors and methods for creating an
EncryptedContentInfoStream
, encrypting its content (thereby
optionally creating a secret content-encryption key in accordance with the
specified content-encryption algorithm), and "re-decrypting" the encrypted
content again.
This class - as in common with all IAIK-JCE PKCS#7 implementations - provides mechanisms for encoding the inherent encrypted content data as indefinite primitive octet string instead of using the default primitive definite encoding scheme:
0x24 0x80 0x04 <blocksize> <first encrypted content block> 0x04 <blocksize> <second encrypted content block> 0x04 <blocksize> <third encrypted content block> ... 0x00 0x00instead of:
0x04 <length> <encrypted content>The indefinite constructed encoding scheme may be preferable for properly handling large amounts of data, or/and when intending to be compatible to the encoding practice of some particular application (for instance some versions of Netscape Navigator).
setBlockSize
method has to be used
for defining the length of each primitive definite encoded octet string
component before actually performing the encoding by means of the
writeTo
method, e.g.:
//create a EncryptedContentInfoStream for the data to be encrypted, supplied from an input stream: InputStream dataStream = ...; EncryptedContentInfoStream eci = new EncryptedContentInfoStream(ObjectID.pkcs7_data, dataStream); //generate secret key and set up the cipher for encryption: SecretKey key = eci.setupCipher(AlgorithmID.des_EDE3_CBC); //optionally set the block size for splitting the encoding: eci.setBlockSize(1024); //perform the content encryption and encode the EncryptedContentInfo to an output stream eci.writeTo(output_stream);Note: in contrast to the equivalent non-stream supporting
EncryptedContentInfo
class,
where the content encryption already is performed when calling a proper
setupCipher
method, this class performs the content encryption
actually during the encoding by piping the data through a cipher stream when
executing the writeTo
method. The
corresponding setupCipher
method only initializes the cipher for
the cipher stream pipe.
In the same way, when parsing an already existing
EncryptedContentInfoStream
object a proper
setupCipher
method has to be used for initializing the cipher
stream pipe for decryption. The decryption actually is performed when reading
the data previously obtained by means of the getInputstream
method:
// create an EncryptedContentInfoStream from the input stream supplying the // encoding: EncryptedContentInfoStream eci = new EncryptedContentInfoStream(encoded_stream); // setup the cipher for decryption using the right secret key: eci.setupCipher(key); // get and read the data thereby actually performing the decryption InputStream data_is = eci.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }Attention! Special care has to be taken when using the default setup methods for initializing the content en/decryption as described above, particularly when the content encryption algorithm requires a specific key/parameter handling. In such cases, alternatively the
setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec)
respectively
setupCipher(Key key,
AlgorithmParameterSpec)
methods shall be used to setup the cipher for
content en/decryption. (see the method descriptions for more information).EnvelopedDataStream
,
SignedAndEnvelopedDataStream
,
EncryptedDataStream
Modifier | Constructor and Description |
---|---|
protected |
EncryptedContentInfoStream()
Default constructor.
|
|
EncryptedContentInfoStream(java.io.InputStream is)
Creates a new EncryptedContentInfoStream where the DER encoded data is read
from the given InputStream.
|
|
EncryptedContentInfoStream(ObjectID contentType,
AlgorithmID contentEncAlg)
Creates an EncryptedContentInfoStream with given content type and
content-encryption algorithm ID.
|
|
EncryptedContentInfoStream(ObjectID contentType,
java.io.InputStream is)
Creates a new EncryptedContentInfoStream for the given content type where
the content data to be encrypted is read from the provided InputStream.
|
Modifier and Type | Method and Description |
---|---|
protected void |
decode(java.io.InputStream is)
Reads and decodes the EncryptedContentInfoStream from a DerInputStream.
|
int |
getBlockSize()
Gets the block size defining the length of each definite primitive encoded
octet string component.
|
AlgorithmID |
getContentEncryptionAlgorithm()
Returns the content-encryption algorithm (including any associated
parameters) of this EncryptedContentInfoStream.
|
ObjectID |
getContentType()
Returns the type of the content encrypted by this
EncryptedContentInfoStream.
|
java.io.InputStream |
getInputStream()
Returns an InputStream for reading the decrypted content.
|
boolean |
hasContent()
Returns
true if there is a content. |
void |
setBlockSize(int blockSize)
Sets the block size for encoding the encrypted content.
|
javax.crypto.SecretKey |
setupCipher(AlgorithmID contentEA)
Setups the cipher and generates a secret key for encrypting the content.
|
javax.crypto.SecretKey |
setupCipher(AlgorithmID contentEA,
int keyLength)
Setups the cipher and generates a secret key for encrypting the content.
|
void |
setupCipher(AlgorithmID contentEA,
java.security.Key key,
java.security.spec.AlgorithmParameterSpec params)
Setups the cipher for encrypting the content.
|
void |
setupCipher(java.security.Key key)
Uses the specified content-encryption key to setup the cipher for
decrypting the content.
|
void |
setupCipher(java.security.Key key,
java.security.spec.AlgorithmParameterSpec params)
Uses the specified key and parameters to setup the cipher for decrypting
the content.
|
ASN1Object |
toASN1Object()
Returns this EncryptedContentInfoStream as ASN1Object.
|
java.lang.String |
toString()
Returns a string giving some information about this
EncryptedContentInfoStream object. |
void |
writeTo(java.io.OutputStream os)
Writes the BER encoding of this object to the given OutputStream.
|
protected EncryptedContentInfoStream()
public EncryptedContentInfoStream(ObjectID contentType, java.io.InputStream is)
contentType
- the PKKCS#7 content typeis
- the input stream holding the content data to encryptpublic EncryptedContentInfoStream(ObjectID contentType, AlgorithmID contentEncAlg)
contentType
- the type of the encrypted contentcontentEncAlg
- the algorithm used to encrypt the contentpublic EncryptedContentInfoStream(java.io.InputStream is) throws java.io.IOException, PKCSParsingException
The given input stream supplies the DER encoding of an already existing
EncryptedContentInfoStream
object that may have been created
by calling writeTo
.
Use the EncryptedContentInfoStream(ObjectID contentType, InputStream is)
constructor for supplying the content to be encrypted when creating an
EncryptedContentInfoStream
object.
is
- the InputStream holding a DER encoded PKCS#7
EncryptedContentInfoStream objectjava.io.IOException
- if an I/O error occurs during reading from the InputStreamPKCSParsingException
- if an error occurs while parsing the objectprotected void decode(java.io.InputStream is) throws java.io.IOException, PKCSParsingException
DerInputStream
, internally a
DerInputStream is created before parsing the data.is
- the InputStream holding a DER encoded PKCS#7
EncryptedContentInfoStream objectjava.io.IOException
- if an I/O error occurs during reading from the InputStreamPKCSParsingException
- if an error occurs while parsing the objectpublic void setupCipher(AlgorithmID contentEA, java.security.Key key, java.security.spec.AlgorithmParameterSpec params) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.InvalidAlgorithmParameterException
writeTo
method. So it is important to setup
the cipher before writing to the stream!
Note: The supplied parameters are used for initializing the cipher. They may, for instance, represent an initialization vector of type IvParameterSpec. In such cases, if the supplied contentEA algorithmID does not include parameters, an OCTET_STRING is created from the iv value and set as parameters for the contentEA algorithmID. However, if the contentEA algorithmID expects parameters of other ASN.1 representation than an OCTET_STRING constituting the IV, an application itself should take care for setting the parameters before supplying the algorithmID to this method. Imagine, for instance, RC2-CBC as used by S/MIME, where the parameters are encoded as SEQUENCE with two components having the OCTET_STRING iV as second component (see RFC 2311):
RC2-CBC parameter ::= SEQUENCE { rc2ParameterVersion INTEGER, iv OCTET STRING (8)}In such case an application may:
contentEA
- the algorithm to use for encrypting the contentkey
- the key to useparams
- the parameters to initialize the cipherjava.security.NoSuchAlgorithmException
- if there is no implementation for the specified algorithmjava.security.InvalidKeyException
- if the key is inappropriate for the content-encryption
algorithmjava.security.InvalidAlgorithmParameterException
- if the provided parameters are not appropriate for the
algorithmpublic javax.crypto.SecretKey setupCipher(AlgorithmID contentEA) throws java.security.NoSuchAlgorithmException
writeTo
method. So it is important to setup
the cipher before writing to the stream!
Attention! This method only shall be used for cipher setup if the
secret key to be generated has a predefined length or default setting,
since no key length parameter is offered. Furthermore, when using this
method for cipher setup, it is expected that the algorithm parameters have
to be encoded as OCTET_STRING. In cases where an alternative encoding is
required (e.g. PBE, RC2), the
setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec)
method shall be
used to setup the cipher for content encryption.
contentEA
- the algorithm to use for encrypting the contentjava.security.NoSuchAlgorithmException
- if there is no implementation for the specified algorithmpublic javax.crypto.SecretKey setupCipher(AlgorithmID contentEA, int keyLength) throws java.security.NoSuchAlgorithmException
keyLength
parameter. If no length is specified, the defined
default key length will be used. If the algorithm only works with keys of
fixed-size length, the keyLength parameter may be set to -1 or the
setupCipher(AlgorithmID)
method may be
used.
This method creates a cipher for the specified content-encryption algorithm
and initializes it with the newly generated secret key. The content
encryption actually is performed during the encoding when writing this
EncyrptedContentInfo to a stream by calling the
writeTo
method. So it is important to setup
the cipher before writing to the stream!
Attention! This method only shall be used for cipher setup if the
algorithm parameters represent an IV that has to be encoded as
OCTET_STRING. In cases where an alternative encoding is required (e.g. PBE,
RC2), the setupCipher(AlgorithmIDA, Key, AlgorithmParameterSpec)
method shall be
used to setup the cipher for content encryption.
contentEA
- the algorithm to use for encrypting the contentkeyLength
- the key length that may be set when using a content encryption
algorithm that supports variable key lengthsjava.security.NoSuchAlgorithmException
- if there is no implementation for the specified algorithmpublic void setupCipher(java.security.Key key, java.security.spec.AlgorithmParameterSpec params) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, java.security.InvalidAlgorithmParameterException
This method shall be used for initializing the cipher of an received
EncryptedContentInfoStream
object with key and parameters for
decrypting the encrypted content, particularly when the parameters of the
content encryption algorithmID do not constitute an OCTET_STRING that
represents IV parameters. The following example parses PBE parameters from
the algorithmID, and subsequently setups the cipher with key and derived
parameters:
// get the content encryption algorithm: AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); // get PBE parameters SEQUENCE seq = (SEQUENCE) contentEA.getParameter; OCTET_STRING oct = (OCTET_STRING) seq.getComponentAt(0); byte[] salt = (byte[]) oct.getValue(); INTEGER iteration_count = (INTEGER) seq.getComponentAt(1); int it = ((BigInteger) iteration_count.getValue()).intValue(); PBEParameterSpec params = new PBEParameterSpec(salt, it); // now setup the cipher eci.setupCipher(pbeKey, params);The decryption actually is performed when subsequently getting and reading the data by means of the
getInputStream
method:
// get and read the data thereby actually performing the decryption InputStream data_is = eci.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }It has to be noticed that the data should not be read before setting up the cipher!
key
- the (secret) key to decrypt the contentparams
- the algorithm parameters needed to decrypt the contentjava.security.NoSuchAlgorithmException
- if there is no implementation for the
content-encryption-algorithm to be usedjava.security.InvalidKeyException
- if the key is inappropriate for the content-encryption
algorithmjava.security.InvalidAlgorithmParameterException
- if the provided parameters are not appropriate for the created
cipherpublic void setupCipher(java.security.Key key) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException, PKCSException
This method shall be used for initializing the cipher of an received
EncryptedContentInfoStream
object with the right secret key
for decrypting the encrypted content. The decryption actually is performed
when subsequently getting and reading the data by means of the
getInputStream
method:
// create an EncryptedContentInfoStream from the input stream supplying the // encoding: EncryptedContentInfoStream eci = new EncryptedContentInfoStream(encoded_stream); // setup the cipher for decryption with the right secret key: eci.setupCipher(key); // get and read the data thereby actually performing the decryption InputStream data_is = eci.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }It has to be noticed that the data should NOT be read before setting up the cipher!
This method tries to get the algorithm parameters from the content encryption
algorithm id. If this is not possible this method tries to create an
IvParameterSpec from the algorithm id parameters (if parameters are present
and are of ASN.1 type OCTET_STRING).
Alternatively you may get the ASN.1 parameters
from the content encryption algorithm id, create a proper AlgorithmParameterSpec
and use method setupCipher(Key key,
AlgorithmParameterSpec)
to setup the cipher for content decryption, e.g. (assuming
an algorithm id containing PBE parameters):
// get the content encryption algorithm: AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); // get PBE parameters SEQUENCE seq = (SEQUENCE) contentEA.getParameter(); OCTET_STRING oct = (OCTET_STRING) seq.getComponentAt(0); byte[] salt = (byte[]) oct.getValue(); INTEGER iteration_count = (INTEGER) seq.getComponentAt(1); int it = ((BigInteger) iteration_count.getValue()).intValue(); PBEParameterSpec params = new PBEParameterSpec(salt, it); // now setup the cipher eci.setupCipher(pbeKey, params);
key
- the (secret) key to decrypt the contentjava.security.NoSuchAlgorithmException
- if there is no implementation for the
content-encryption-algorithm to be usedjava.security.InvalidKeyException
- if the key is inappropriate for the content-encryption
algorithmPKCSException
- if the algorithm parameter cannot be retrieved from the
algorithmpublic void setBlockSize(int blockSize)
blockSize
is positive, the encrypted 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 0x00If
blockSize
is not positive, whole the encrypted content is
encoded as definite primitive octet string when calling the
writeTo
method:
0x04 <length> <encrypted content>
blockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if
positivepublic int getBlockSize()
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 EncryptedData into a ContentInfo.OCTET_STRING
public ASN1Object toASN1Object() throws PKCSException
EncryptedContentInfoStream
as ASN1Object.PKCSException
public void writeTo(java.io.OutputStream os) throws java.io.IOException, PKCSException
When encoding the content data to the given stream it is piped through a cipher stream thereby performing the content encryption.
If the setBlockSize
method has been utilized for
defining a positive blockSize
value, the encrypted 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, whole the encrypted content is encoded as definite primitive octet string:
0x04 <length> <encrypted content>
os
- the OutputStream to which the encoding shall be written tojava.io.IOException
- if an I/O error occurs during writing to the OutputStreamPKCSException
- if an error occurs while encoding the objectpublic ObjectID getContentType()
public AlgorithmID getContentEncryptionAlgorithm()
public java.io.InputStream getInputStream()
When having created a new EncryptedContentInfoStream
object to
be encoded to a stream, this method should not be utilized at all, since
the stream automatically will be read during performing the encoding (which
is done when calling the writeTo
method).
When having decoded and parsed a received
EncryptedContentInfoStream
object coming from some stream,
this method may be used for obtaining the raw (decrypted) data after having
done the cipher setup.
public boolean hasContent()
true
if there is a content.true
if there is a contentpublic java.lang.String toString()
EncryptedContentInfoStream
object.toString
in class java.lang.Object