|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--iaik.pkcs.pkcs7.EnvelopedDataStream
This class represents the stream-supporting implementation of the PKCS#7 content
type EnvelopedData
.
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 EnvelopedData
content type is
defined as:
envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3 }
which corresponds to the OID string "1.2.840.1.113549.1.7.3".
The PKCS#7
Cryptographic Message Standard specifies the EnvelopedData
content type for providing a syntax for building digital envelopes. Content
of any type may be enveloped for any number of recipients in parallel. For
each recipient, a commonly at random generated content-encryption key is
encrypted with the particular recipientīs public key and - together with
recipient-specific information - collected into a RecipientInfo
value. The content is encrypted with the content-encryption key giving a
EncryptedContent
value, which - in combination with a
recipient-specific encrypted content-encryption key - forms the digital
envelope for each particular recipient. All RecipientInfo
values are collected together with the encrypted content into an
EnvelopedData
value to be sent to each intended recipient.
This class implements the EnvelopedData
structure resulting from
the last step described above. The EnvelopedData
type is defined
as ASN.1 SEQUENCE type containing the following components (see PKCS#7 specification,
Version 1.5):
EnvelopedData ::= SEQUENCE { version Version, recipientInfos RecipientInfos, encryptedContentInfo EncryptedContentInfo }
RecipientInfos ::= SET OF RecipientInfo
EncryptedContentInfo ::= SEQUENCE { contentType ContentType, contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
EncryptedContent ::= OCTET STRING
The recipientInfos
field is a non-empty collection of
per-recipient information. The encryptedContentInfo
field
specifies the type of the content being enveloped, the content-encryption
algorithm (the same for all recipients) 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.
A recipient, when receiving the EnvelopedData
message,
decrypts the corresponding encrypted content-encryption key with his/her
private key for subsequently decrypting the encrypted content using the
content-encryption key just recovered. The recipient's private key is
referenced by an issuer distinguished name and an issuer-specific serial
number that uniquely identify the certificate for the corresponding public
key.
For more information consult the RSA PKCS#7 specification.
When creating a new EnvelopedDataStream
object for the data to be enveloped
the symmetric algorithm has to be specified to be used for content-encryption. After setting
the recipients, the EnvelopedDataStream object may be encoded and written to an output stream
by using a proper writeTo
method, e.g.:
EnvelopedDataStream(InputStream is, AlgorithmID contentEA)
constructor:
//the data to be enveloped supplied from an input stream: InputStream dataStream = ...; //use TripleDES in CBC mode for encrypting the content EnvelopedDataStream enveloped_data = new EnvelopedDataStream(dataStream, AlgorithmID.des_EDE3_CBC);
RecipientInfo
object, and add all RecipientInfos to the EnvelopedDataStream
structure by calling the setRecipientInfos
method, e.g.
(assuming to add two recipients with corresponding certificates cert1
and
cert2
; currently only the PKCS#1 rsaEncryption is supported as key-
encryption algorithm):
RecipientInfo[] recipients = new RecipientInfo[2]; recipients[0] = new RecipientInfo(cert1, AlgorithmID.rsaEncryption); recipients[1] = new RecipientInfo(cert2, AlgorithmID.rsaEncryption); enveloped_data.setRecipientInfos(recipients);
writeTo
method for BER encoding the
EnvelopedData object and writing it to an output stream. You optionally may specify
a particular block size for splitting the encoding of encrypted content. This step
also will perform the encryption of the symmetric content-encryption key for each
participated recipient.
int blockSize = ...; OutputStream encoded_stream = ...; enveloped_data.writeTo(encoded_stream, blockSize);respectively
enveloped_data.writeTo(encoded_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
EnvelopedData 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
EnvelopedData
implementation.
When a positve block size is specified for encoding the EnvelopedData 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:
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 indefinte constrcuted encoding scheme also may be preferable when intending to be compatible to the encoding practice of some particular application (for instance some versions of Netscape Navigator).
EnvelopedDataStream(InputStream is)
constructor for parsing the internal structure. Before reading the recovered content by means of the
getInputStream
method, the cipher has to be
initialized for decryption with the particular recipientīs private key by calling the
setupCipher
method:
EnvelopedDataStream enveloped_data = new EnvelopedDataStream(encoded_stream);
EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo(); System.out.println("Content type: "+eci.getContentType().getName()); System.out.println("Content encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
RecipientInfo[] recipients = enveloped_data.getRecipientInfos(); System.out.pritnln("Included RecipientInfos:"); for (int i=0; i < recipients.length; i++) { System.out.print("Recipient "+(i+1)+":"); System.out.println(recipients[i].getIssuerAndSerialNumber()); }
//setup cipher for recipient 1: int recipientInfoIndex = 0; enveloped_data.setupCipher(privateKey, recipientInfoIndex);Unlike the non-stream supporting
EnvelopedData
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 = enveloped_data.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }
RecipientInfo
,
EncryptedContentInfoStream
Field Summary | |
protected int |
block_size
The block size for block oriented stream encoding. |
protected EncryptedContentInfoStream |
encrypted_content_info
The EncryptedContentInfo for the encrypted content. |
protected Vector |
recipient_infos
Repository for the RecipientInfos. |
protected SecretKey |
symmetric_key
The secret content encryption key. |
protected int |
version
The version number; currently 0. |
Constructor Summary | |
protected |
EnvelopedDataStream()
Default constructor for dynamic object creation in ContentInfo. |
|
EnvelopedDataStream(InputStream is)
Creates a new EnvelopedDataStream where the DER encoded data is read from the given InputStream. |
|
EnvelopedDataStream(InputStream is,
AlgorithmID contentEA)
Creates a new PKCS#7 EnvelopedDataStream object where the content to be enveloped is read from the supplied InputStream. |
|
EnvelopedDataStream(InputStream is,
AlgorithmID contentEA,
int keyLength)
Creates a new PKCS#7 EnvelopedDataStream object where the content to be enveloped is read from the supplied InputStream. |
|
EnvelopedDataStream(RecipientInfo[] recipients,
EncryptedContentInfoStream encryptedCI)
Constructs an EnvelopedDataStream object with an already created EncryptedContentInfoStream. |
Method Summary | |
void |
addRecipientInfo(RecipientInfo recipient)
Adds one recipient to the list of recipient infos. |
void |
decode(InputStream is)
Reads and decodes the EnvelopedData 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. |
Object |
getEncryptedContentInfo()
Returns the encrypted content info included in this EnvelopedDataStream object.
|
InputStream |
getInputStream()
Returns an InputStream from where the decrypted data can be read. |
RecipientInfo |
getRecipientInfo(X509Certificate recipientCertificate)
Returns the recipient info matching to the supplied recipient certificate. |
RecipientInfo[] |
getRecipientInfos()
Returns all the recipient infos included in this EnvelopedData object. |
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 |
setRecipientInfos(RecipientInfo[] recipients)
Sets the recipient infos. |
void |
setupCipher(Key key)
Uses the given symmetric key to setup the cipher for decrypting the content. |
void |
setupCipher(PrivateKey recipientPrivateKey,
int recipientInfoIndex)
Uses the specified private key to setup the Cipher for decrypting the content-encryption key and subsequently using it to decrypt the encrypted content of this
EnvelopedDataStream object for the requesting recipient, specified by its
recipientInfoIndex .
|
ASN1Object |
toASN1Object()
Returns this EnvelopedDataStream as ASN1Object. |
protected ASN1Object |
toASN1Object(int blockSize)
Returns this EnvelopedData as ASN1Object. |
String |
toString()
Returns a string giving some information about this EnvelopedData object. |
String |
toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this EnvelopedData object. |
void |
writeTo(OutputStream os)
DER encoded this EnvelopedData and writes the encoding to the supplied output stream. |
void |
writeTo(OutputStream os,
int blockSize)
Writes the BER encoding of this EnvelopedData to the supplied output stream where a constructed OCTET STRING is used for encoding the content. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
protected int version
protected Vector recipient_infos
protected EncryptedContentInfoStream encrypted_content_info
protected SecretKey symmetric_key
protected int block_size
Constructor Detail |
protected EnvelopedDataStream()
public EnvelopedDataStream(InputStream is, AlgorithmID contentEA) throws NoSuchAlgorithmException
When using this constructor, automatically a symmetric key for content
encryption is generated. For that reason this constructor shall not be used
in situations where the desired content encryption algorithm requires a
specific key/parameter handling. In such cases the EnvelopedDataStream(RecipientInfo[], EncryptedContentInfoStream)
constructor shall be used to be supplied with precomputed RecipientInfos
and EncryptedContentInfo. Consult the EncryptedContentInfoStream
class documentation for more information about
special key/parameter handling.
is
- the InputStream containing the data to envelopecontentEA
- the content encryption algorithm for encrypting the contentNoSuchAlgorithmException
- if there is no implementation for the specified algorithmpublic EnvelopedDataStream(InputStream is, AlgorithmID contentEA, int keyLength) throws NoSuchAlgorithmException
When using this constructor, automatically a symmetric key for content
encryption is generated.
If the specified content encryption algorithm supports variable key lengths, a
particular key length may be set by means of the 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 EnvelopedDataStream(InputStream is, AlgorithmID contentEA)
constructor may be used.
This constructor shall not be used in situations where the desired content encryption
algorithm requires a specific parameter handling. In such cases the EnvelopedDataStream(RecipientInfo[], EncryptedContentInfoStream)
constructor shall be used to be supplied with precomputed RcipientInfos
and EncryptedContentInfo. Consult the EncryptedContentInfoStream
class documentation for more information about
special key/parameter handling.
is
- the InputStream containing the data to envelopecontentEA
- the content encryption algorithm for encrypting the contentkeyLength
- the key length that may be set when using a content
encryption algorithm that supports variable key lengthsNoSuchAlgorithmException
- if there is no implementation for the specified algorithmpublic EnvelopedDataStream(RecipientInfo[] recipients, EncryptedContentInfoStream encryptedCI)
RecipientInfo
specifies a collection of
per-recipient information, and the given EncryptedContentInfoStream
supplies the already encrypted content.recipients
- information about the recipientsencryptedCI
- the encrypted content infopublic EnvelopedDataStream(InputStream is) throws PKCSParsingException, IOException
is
- the InputStream holding a DER encoded PKCS#7 EnvelopedData objectIOException
- if an I/O error occurs during reading from the InputStreamPKCSParsingException
- if an error occurs while parsing the objectMethod Detail |
public void decode(InputStream is) throws 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 EnvelopedData objectIOException
- if an I/O error occurs during reading from the InputStreamPKCSParsingException
- if an error occurs while parsing the objectpublic ObjectID getContentType()
getContentType
in interface ContentStream
ObjectID.pkcs7_envelopedData
public void setRecipientInfos(RecipientInfo[] recipients)
RecipientInfo
specifies the particular recipientīs certificate by IssuerAndAserialNumber, and the
key encryption algorithm to be used; currently only PKCS#1 rsaEncryption is supported.
Example:
RecipientInfo[] recipients = new RecipientInfo[2]; recipients[0] = new RecipientInfo(cert1, AlgorithmID.rsaEncryption); recipients[1] = new RecipientInfo(cert2, AlgorithmID.rsaEncryption); enveloped_data.setRecipientInfos(recipients);
recipients
- a collection of per-recipient informationRecipientInfo
public void addRecipientInfo(RecipientInfo recipient)
The RecipientInfo
specifies the particular recipientīs
certificate by IssuerAndAserialNumber, and the
key encryption algorithm to be used; currently only PKCS#1 rsaEncryption is supported.
Example:
RecipientInfo recipient = new RecipientInfo(cert, AlgorithmID.rsaEncryption); enveloped_data.addRecipientInfo(recipient);
recipient
- the RecipientInfo to be addedpublic void setBlockSize(int blockSize)
blockSize
is smaller or equal to zero the
whole encrypted data is encoded as definite primitive octet string.
This method may be used for enforcing block encoding when wrapping the
EnvelopedData 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 setupCipher(PrivateKey recipientPrivateKey, int recipientInfoIndex) throws PKCSException, NoSuchAlgorithmException, InvalidKeyException
EnvelopedDataStream
object for the requesting recipient, specified by its
recipientInfoIndex
.
This method first uses the given private key for decrypting the encrypted
temporary symmetric key obtained from the corresponding RecipientInfo
structure, and subsequently uses this key to initialize a CipherInputStream for
the inherent encrypted content.
Unlike the non-stream supporting EnvelopedData
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
encryption AlgorithmID contains IV parameters encoded as an OCTET_STRING. When
the algorithmID contains parameters of other type (e.g. S/MIME RC2-CBC parameters)
they have to be decoded separatly, and the setupCipher(Key key, AlgorithmParameterSpec)
method of the EncryptedContentInfoStream
class has to be used to setup the cipher for content decryption, e.g.:
//get the ECI from the enveloped data: EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo(); // get the recipient infos RecipientInfo[] recipients = enveloped_data.getRecipientInfos(); // use the specific recipientīs private key for decrypting the required // symmetric content encryption key, e.g.: SecretKey secretKey = recipient_infos[0].decryptKey(recipientPrivateKey) //get the content encryption algorithm: AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); // get the parameters as SEQUENCE SEQUENCE seq = (SEQUENCE)contentEA.getParameter(); // the iv is the second component OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1); // create an IvParameterSpec: IvParameterSpec ivSpec = new IvParameterSpec(oct.getValue()); //now setup the cipher with previously decrypted recipient key amd params eci.setupCipher(secretKey, ivSpec); //get and read the data thereby actually performing the decryption InputStream data_is = signed_data.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }
recipientPrivateKey
- the private key of the recipient to be used for decrypting
the encrypted content-encryption key.recipientInfoIndex
- specifies which RecipientInfo the private key belongs toPKCSException
- if there occurs an error while decrypting the dataNoSuchAlgorithmException
- if there is no implementation of the content-encryption algorithmInvalidKeyException
- if the specified private key is not validpublic void setupCipher(Key key) throws PKCSException, NoSuchAlgorithmException, InvalidKeyException
Unlike the non-stream supporting EnvelopedData
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
encryption AlgorithmID contains IV parameters encoded as an OCTET_STRING. When
the algorithmID contains parameters of other type (e.g. S/MIME RC2-CBC parameters)
they have to be decoded separatly, and the setupCipher(Key key, AlgorithmParameterSpec)
method of the EncryptedContentInfoStream
class has to be used to setup the cipher for content decryption, e.g.:
//get the ECI from the enveloped data: EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo(); //get the content encryption algorithm: AlgorithmID contentEA = eci.getContentEncryptionAlgorithm(); // get the parameters as SEQUENCE SEQUENCE seq = (SEQUENCE)contentEA.getParameter(); // the iv is the second component OCTET_STRING oct = (OCTET_STRING)seq.getComponentAt(1); // create an IvParameterSpec: IvParameterSpec ivSpec = new IvParameterSpec(oct.getValue()); //now setup the cipher with previously decrypted recipient key amd params eci.setupCipher(secretKey, ivSpec); //get and read the data thereby actually performing the decryption InputStream data_is = signed_data.getInputStream(); byte[] buf = new byte[1024]; int r; while ((r = data_is.read(buf)) > 0) { // do something useful }
key
- the temporary symmetric key that has been used to encrypt the content,
and now is used for decrypting it againPKCSException
- if there occurs an error while decrypting the dataNoSuchAlgorithmException
- if there is no implementation for the content-encryption algorithmInvalidKeyException
- if the specified private key is not validpublic InputStream getInputStream()
When having created a new EnvelopedDataStream
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.
public int getVersion()
public RecipientInfo[] getRecipientInfos()
EnvelopedData
object.RecipientInfo
objects
included into this EnvelopedData
setRecipientInfos(iaik.pkcs.pkcs7.RecipientInfo[])
public RecipientInfo getRecipientInfo(X509Certificate recipientCertificate)
null
if no recipient info belonging to the given
certificate can be foundsetRecipientInfos(iaik.pkcs.pkcs7.RecipientInfo[])
public Object getEncryptedContentInfo()
EnvelopedDataStream
object.
When calling this method for obtaining the inherent EncryptedContentInfoStream
an explicit cast to EncryptedContentInfoStream
has to be made:
EncryptedContentInfoStream eci = (EncryptedContentInfoStream)enveloped_data.getEncryptedContentInfo();
public ASN1Object toASN1Object() throws PKCSException
toASN1Object
in interface ContentStream
EnvelopedDataStream
as ASN1Object.PKCSException
- if the ASN1Object could not be createdprotected ASN1Object toASN1Object(int blockSize) throws PKCSException
If
blockSize
- the block size defining the encoding scheme - and specifying the
length of each primitive encoded octet string component, if positiveEnvelopedData
as ASN1ObjectPKCSException
- if the ASN1Object could not be created
public void writeTo(OutputStream os) throws IOException
os
- the output stream to which this EnvelopedData shall be writtenpublic void writeTo(OutputStream os, int blockSize) throws IOException
When encoding the content data to the given stream it is piped through a cipher stream thereby performing the content encryption.
If the a positive blockSize
value is specified, 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 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 positiveIOException
- if an error occurs during writing the objectpublic String toString()
EnvelopedData
object.toString
in class Object
public String toString(boolean detailed)
EnvelopedData
object.toString
in interface ContentStream
detailed
- - whether or not to give detailed information
|
This Javadoc may contain text parts from Internet Standard specifications (RFC 2459, 3280, 3039, 2560, 1521, 821, 822, 2253, 1319, 1321, ,2630, 2631, 2268, 3058, 2984, 2104, 2144, 2040, 2311, 2279, see copyright note) and RSA Data Security Public-Key Cryptography Standards (PKCS#1,3,5,7,8,9,10,12, see copyright note). | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |