public class EncryptedDataStream extends java.lang.Object implements ContentStream
EncryptedData
type.
Each PKCS#7 content type is associated with a specific object identifier, derived from:
pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1) 7 }
The object identifier for the EncryptedData
content type is
defined as:
encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 }
which corresponds to the OID string "1.2.840.1.113549.1.7.6".
The PKCS#7
Cryptographic Message Standard specifies the EncryptedData
content type for providing a syntax for building encrypted contents. The
encrypted-data content type consists of encrypted content of any type
(Version 1.5):
EncryptedData ::= SEQUENCE { version Version, encryptedContentInfo EncryptedContentInfo }
The encryptedContentInfo
field specifies the type of the content
being encrypted, the content-encryption algorithm used for encrypting the
content, and the result of the content encryption. If the encrypted content
value is not present in the encryptedContent
field, it has to be
supplied by other means:
EncryptedContentInfo ::= SEQUENCE { contentType ContentType, contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
EncryptedContent ::= OCTET STRING
The key that is used for encrypting the content is not included in the
EncryptedData
structure, it is assumed to be managed by other
means.
When creating a new EncryptedDataStream
instance the encrypted
content has to be supplied as
EncryptedContentInfoStream
object.
Example:
//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);
//create an EncryptedDataStream for the EncryptedContentInfoStream:
EncryptedDataStream encrypted_data = new EncryptedDataStream(eci);
//DER encode the EncryptedDataStream
structure and write the encoding to an
//output stream:
OutputStream encoded_stream = ...;
int blockSize = ...;
encrypted_data.writeTo(encoded_stream, blockSize);
If a positive blocksize is specified, the encrypted content of the inherent
EncryptedContentInfoStream will be encoded 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).
Decrypting goes the reverse way: From the DER encoded
encryptedData
a new EncryptedDataStream
is created
and parsed for the inherent EncryptedContentInfoStream
. From the
EncryptedContentInfoStream
the encrypted content is obtained and
decrypted using the same secret key:
EncryptedDataStream encryptedData = new EncryptedDataStream(encoded_stream); EncryptedContentInfoStream eci = (EncryptedContentInfoStream) encryptedData .getEncryptedContentInfo(); // 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 }
This class additionally supports specific constructors and methods allowing to
easily use the EncryptedData content type for password based encrypting data
-- the intended usage of PKCS#7 EncryptedData. Please remark that the
following proceeding only may be used when doing a password based encryption.
In all other situations you have to follow the way described above. However,
you also may create your own EncryptedContentInfoStream
even
when doing a PBE encryption.
If you want to use PBE encryption but not creating an
EncryptedContentInfoStream
by yourself you first have to supply
the data to be read from an inputstream, subsequently setup the cipher for
PBE-encryption and finally call a writeTo
method for encoding
the EncryptedData object to a stream:
EncryptedDataStream(InputStream is, int blockSize)
constructor for creating
a new EncryptedDataStream
object and supplying the data to be
encrypted from an inputstream. You optionally may define a particular
blockSize
value for splitting the encoding of the encrypted
content:
//the data to be encrypted supplied from an input stream: InputStream dataStream = ...; // the block size: int blockSize = ...; EncryptedDataStream encrypted_data = new EncryptedDataStream(dataStream, blockSize);
setupCipher(AlgorithmID contentEA,
char[] password)
thereby specifying the PBE-algorithm to be used and the
password, e.g.:
AlgorithmID pbeAlgorithm = AlgorithmID.pbeWithSHAAnd3_KeyTripleDES_CBC; char[] password = ...; encrypted_data.setupCipher(pbeAlgorithm, password);
writeTo
method for BER
encoding the EncryptedData object and writing it to an output stream. If not
yet done you optionally may specify a particular block size for splitting the
encoding of encrypted content.
int blockSize = ...; OutputStream encoded_stream = ...; encrypted_data.writeTo(encoded_stream, blockSize);respectively
encryptped_data.writeTo(encoded_stream);It is recommended to use a positive block size value, because it is the intended purpose of this stream-supporting EncryptedData implementation to handle large amounts of data. When no block size is specified whole the encrypted content is encoded as primitive definite octet string, which advantageously may be done when using the non-stream supporting
EncryptedData
implementation. When a
positive block size is specified for encoding the EncryptedData to a stream,
the encrypted content is BER encoded as indefinite constructed octet string
being composed of a series of definite primitive encoded octet strings of
blockSize
length.
EncryptedDataStream(InputStream is)
constructor to parse the internal
structure. Before reading the recovered content by means of the
getInputStream
method, the cipher has to be
initialized for decryption with the password by calling the
setupCipher(char[] password)
method:
ASN1Object obj = DerCoder.decode(encoding);
EncryptedData encrypted_data = new EncryptedData(obj);
EncryptedContentInfoStream eci = (EncryptedContentInfoStream) encrypted_data .getEncryptedContentInfo(); System.out.println("Content type: " + eci.getContentType().getName()); System.out.println("Content encryption algorithm: " + eci.getContentEncryptionAlgorithm().getName());
char[] password = ...; encrypted_data.setupCipher(password);Unlike the non-stream supporting
EncryptedData
class where the encrypted-content decryption already is
performed inside the setupCipher
method, the cipher will be only
initialized for decryption in this class. The encrypted-content decryption
actually is done during reading the data obtained by calling the
getInputStream
method. So don't call
getInputStream
before setting up the cipher!
InputStream data_is = encrypted_data.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }
EncryptedContentInfoStream
Modifier and Type | Field and Description |
---|---|
protected int |
block_size
The block size for block oriented stream encoding.
|
protected int |
version
This class implements version 0 of the standard
|
Modifier | Constructor and Description |
---|---|
protected |
EncryptedDataStream()
Default constructor for dynamic object creation in ContentInfo.
|
|
EncryptedDataStream(EncryptedContentInfoStream encryptedContentInfo)
Creates a PKCS#7 EncryptedDataStream from an EncryptedContentInfoStream.
|
|
EncryptedDataStream(java.io.InputStream is)
Creates a new EncryptedDataStream where the DER encoded data is read from
the given InputStream.
|
|
EncryptedDataStream(java.io.InputStream is,
int blockSize)
Creates a new PKCS#7 EncryptedDataStream object where the content to be
encrypted is read from the supplied InputStream.
|
Modifier and Type | Method and Description |
---|---|
void |
decode(java.io.InputStream is)
Reads and decodes the EncryptedDataStream from a DerInputStream.
|
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.
|
java.lang.Object |
getEncryptedContentInfo()
Returns the encrypted content info of this
EncryptedDataStream
object. |
java.io.InputStream |
getInputStream()
Returns an InputStream from where the decrypted data can be read.
|
int |
getVersion()
Returns the syntax version number.
|
void |
setBlockSize(int blockSize)
Sets the block size for defining the length of each definite primitive
encoded octet string component.
|
void |
setupCipher(AlgorithmID contentEA,
char[] password)
Setups the cipher for PBE-encrypting the content.
|
void |
setupCipher(AlgorithmID contentEA,
char[] password,
int iterationCount)
Setups the cipher for PBE-encrypting the content.
|
void |
setupCipher(char[] password)
Uses the given password to setup the cipher for decrypting the content.
|
ASN1Object |
toASN1Object()
Returns this PKCS#7 EnvelopedDataStream as ASN1Object.
|
protected ASN1Object |
toASN1Object(int blockSize)
Returns this PKCS#7
EncryptedDataStream as ASN1Object where a
constructed OCTET STRING is used for encoding the encrypted content. |
java.lang.String |
toString()
Returns a string giving some information about this
EncryptedDataStream object. |
java.lang.String |
toString(boolean detailed)
Returns a string giving some - if requested - detailed information about
this
EncryptedDataStream object. |
void |
writeTo(java.io.OutputStream os)
BER encodes and writes this EnvelopedDataStream to the supplied output
stream.
|
void |
writeTo(java.io.OutputStream os,
int blockSize)
Writes this object to the supplied output stream where a constructed OCTET
STRING is used for encoding the content.
|
protected int version
protected int block_size
protected EncryptedDataStream()
public EncryptedDataStream(EncryptedContentInfoStream encryptedContentInfo)
encryptedContentInfo
- the already created encrypted content infopublic EncryptedDataStream(java.io.InputStream is, int blockSize)
This constructor only shall be used when intending to PBE encrypt the data
by subsequently calling method
setupCipher
thereby
supplying PBE-algorithm and password to be used.
This constructor shall not be used in situations where the desired content
encryption algorithm is not a PBE algorithm. In such cases the
EncryptedDataStream(EncryptedContentInfoStream)
constructor shall be used
to be supplied with a precomputed EncryptedContentInfo. Consult the
EncryptedContentInfoStream
class documentation for more information about
EncryptedContentInfo handling.
is
- the InputStream containing the data to encryptblockSize
- for defining the encoding scheme and setting the octet string
component length, if positivepublic EncryptedDataStream(java.io.InputStream is) throws java.io.IOException, PKCSParsingException
is
- the InputStream holding a DER encoded PKCS#7 EncryptedDataStream
objectjava.io.IOException
- if an I/O error occurs during reading from the InputStreamPKCSParsingException
- if an error occurs while parsing the objectpublic void setBlockSize(int blockSize)
blockSize
is
smaller or equal to zero the whole data is encoded as definite primitive
octet string. This method may be used for enforcing block encoding when
wrapping the EncryptedData into a ContentInfo.setBlockSize
in interface ContentStream
blockSize
- for defining the encoding scheme and setting the octet string
component length, if positiveOCTET_STRING
public 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.getBlockSize
in interface ContentStream
OCTET_STRING
public void decode(java.io.InputStream is) throws java.io.IOException, PKCSParsingException
DerInputStream
, internally a
DerInputStream is created before parsing the data.decode
in interface ContentStream
is
- the InputStream holding a DER encoded PKCS#7 EncryptedDataStream
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, char[] password) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
EncryptedDataStream
object by means of the
EncryptedDataStream(InputStream is, int blockSize)
constructor. The
content encryption actually is performed during the encoding when writing
this EncyrptedData to a stream by calling the
writeTo
method. So it is important to setup
the cipher before writing to the stream!
contentEA
- the PBE-algorithm to be usedpassword
- the passwordjava.security.NoSuchAlgorithmException
- if the algorithm is not supportedjava.security.InvalidKeyException
- if the key cannot be derived from the passwordpublic void setupCipher(AlgorithmID contentEA, char[] password, int iterationCount) throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
EncryptedDataStream
object by means of the
EncryptedDataStream(InputStream is, int blockSize)
constructor. The
content encryption actually is performed during the encoding when writing
this EncyrptedData to a stream by calling the
writeTo
method. So it is important to setup
the cipher before writing to the stream!
This method has an additional parameter: iterationCount. When deriving the symmetric key and the IV a hash is calculated iterationCount times on the password and on the salt thus increasing the cost for breaking the cipher using brute force methods.
contentEA
- the PBE-algorithm to be usedpassword
- the passworditerationCount
- the iteration count for key derivationjava.security.NoSuchAlgorithmException
- if the algorithm is not supportedjava.security.InvalidKeyException
- if the key cannot be derived from the passwordpublic void setupCipher(char[] password) throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException, java.security.spec.InvalidParameterSpecException, java.security.InvalidKeyException
Unlike the non-stream supporting EncryptedData
class where the encrypted-content decryption already is
performed inside the setupCipher
method, the cipher will be
only initialized for decrypting in this class. The encrypted-content
decryption actually is done during reading the data obtained by calling the
getInputStream
method. So don't call
getInputStream
before setting up the cipher!
Attention! This method only can be used when the content has been
encrypted using a PBE cipher. Otherwise the
setupCipher(Key key, AlgorithmParameterSpec)
method of the
EncryptedContentInfoStream
class has to be used to setup the cipher for
content decryption.
password
- the passwordjava.security.NoSuchAlgorithmException
- if the algorithm is not supportedjava.security.InvalidKeyException
- if the key cannot be derived from the passwordjava.security.InvalidAlgorithmParameterException
- if the parameters cannot be retrieved from the algorithm IDjava.security.spec.InvalidParameterSpecException
- if the parameters cannot be set uppublic ObjectID getContentType()
getContentType
in interface ContentStream
ObjectID.pkcs7_encryptedData
public int getVersion()
public java.io.InputStream getInputStream()
When having created a new EncryptedDataStream
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 a writeTo
method).
When having decoded and parsed a received EnvelopedDataStream
object comimg from some stream, this method may be used for obtaining the
raw (decrypted) data after having setup the cipher (if PBE-encryption is
used).
public ASN1Object toASN1Object() throws PKCSException
toASN1Object
in interface ContentStream
EnvelopedData
as ASN1Object.PKCSException
- if the ASN1Object could not be createdprotected ASN1Object toASN1Object(int blockSize) throws PKCSException
EncryptedDataStream
as ASN1Object where a
constructed OCTET STRING is used for encoding the encrypted content.blockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if
positiveEncryptedDataStream
as ASN1ObjectPKCSException
- if the ASN1Object could not be createdpublic void writeTo(java.io.OutputStream os) throws java.io.IOException
os
- the output stream to which this EnvelopedDataStream shall be
writtenjava.io.IOException
public void writeTo(java.io.OutputStream os, int blockSize) throws java.io.IOException
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).
os
- the output stream to which this SignedData shall be writtenblockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if
positivejava.io.IOException
- if an error occurs during writing the objectpublic java.lang.Object getEncryptedContentInfo()
EncryptedDataStream
object. When calling this method for obtaining the inherent
EncryptedContentInfoStream
an explicit cast to
EncryptedContentInfoStream
has to be made:
EncryptedContentInfoStream eci = (EncryptedContentInfoStream) encrypted_data .getEncryptedContentInfo();
public java.lang.String toString()
EncryptedDataStream
object.toString
in class java.lang.Object
public java.lang.String toString(boolean detailed)
EncryptedDataStream
object.toString
in interface ContentStream
detailed
- - whether or not to give detailed information