|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object iaik.cms.SignedDataStream iaik.cms.SignedDataInOutStream
public class SignedDataInOutStream
SignedDataStream implementation that encodes a SignedData object again during parsing is done. The SignedData object may be modified before finishing the encoding.
When creating
a SignedDataInOutStream
object an input stream has to specified from which
to read the encoded SignedData object, and an output stream to which to write
the (maybe modified) SignedData object again:
// input stream from which to read the already existing encoded SignedData object: InputStream is = ...; // output stream to which to write the (maybe modified) SignedData object again: OutputStream os = ...; SignedDataInOutStream signedData = new SignedDataInOutStream(is, os);Additionally an array of digest algorithm ids may be specified to be added to the list of digest algorithms of the already existing SignedData. Additional digest algorithms may be necessary when, for instance, adding a new SignerInfo that uses a digest algorithm that is not used by any of the already included SignerInfos, e.g.:
// input stream from which to read the already existing encoded SignedData object: InputStream is = ...; // output stream to which to write the (maybe modified) SignedData object again: OutputStream os = ...; // we want add a SignerInfo that used SHA-256 AlgorithmID[] additionalDigestAlgs = { AlgorithmID.sha256 }; SignedDataInOutStream signedData = new SignedDataInOutStream(is, os, additionalDigestAlgs);It is necessary to specify any additional digest algorithm already when creating the
SignedDataInOutStream
object because they have to be known for the initial SignedData
digestAlgorithms
field.
The further proceeding is similar to that of parent class SignedDataStream
except for using method
for finishing the SignedData
encoding instead of using method write()
writeTo(OutputStream)
. Since the output
stream is already set when creating
the SignedDataInOutStream object, it is not required as parameter for the
final write()
method, e.g.:
// input stream from which to read the already existing encoded SignedData object: InputStream is = ...; // output stream to which to write the (maybe modified) SignedData object again: OutputStream os = ...; // we want add a SignerInfo that used SHA-256 AlgorithmID sha256 = (AlgorithmID)AlgorithmID.sha256.clone(); AlgorithmID[] additionalDigestAlgs = { sha256 }; SignedDataInOutStream signedData = new SignedDataInOutStream(is, os, additionalDigestAlgs); // in explicit mode explicitly supply the content for hash computatio if (signedData.getMode() == SignedDataStream.EXPLICIT) { signed_data.setInputStream(new ByteArrayInputStream(message)); } // get an InputStream for reading the signed content InputStream data = signed_data.getInputStream(); OutputStream dataStream = ...; Util.copyStream(data, dataStream, new byte[4096]); // verify the signature(s) of the already included SignerInfo(s) SignerInfo[] signerInfos = signedData.getSignerInfos(); int numberOfSigners = signerInfos.length; if (numberOfSigners == 0) { String warning = "Warning: Unsigned message (no SignerInfo included)!" System.err.println(warning); throw new CMSException(warning); } else { for (int i=0; i < numberOfSigners; i++) { try { // verify the signed data using the SignerInfo at index i X509Certificate signerCert = signedData.verify(i); // if the signature is OK the certificate of the signer is returned System.out.println("Signature OK from signer: "+signerCert.getSubjectDN()); } catch (SignatureException ex) { // if the signature is not OK a SignatureException is thrown System.err.println("Signature ERROR from signer: "+signedData.getCertificate((signerInfos[i].getSignerIdentifier())).getSubjectDN()); throw new CMSException(ex.toString()); } } } // create and add a new SignerInfo using SHA-256 as digest algorithm X509Certificate signerCert = ...; PrivateKey signerKey = ...; SignerInfo signerInfo = new SignerInfo(new IssuerAndSerialNumber(signerCert), sha256, signerKey); // create some signed attributes (the message digest attribute is automatically added) Attribute[] attributes = new Attribute[2]; // content type is data CMSContentType contentType = new CMSContentType(ObjectID.cms_data); attributes[0] = new Attribute(contentType); // signing time is now SigningTime signingTime = new SigningTime(); attributes[1] = new Attribute(signingTime); // set the attributes signerInfo.setSignedAttributes(attributes); // add SignerInfo to SignedData signedData.addSignerInfo(signer_info); // add the signer certificate signedData.addCertificates(new Certificate[] { signerCert }); // finish the SignedData encoding SignedData.write();Note that in difference to the
writeTo
method of class SignedDataStream
method write
already wraps the SignedData into a ContentInfo.
Note that adding/removing/modifying attributes in already included SignerInfos has
to be done with care when wanting to encode the SignedData anew. The encoding
of attributes / attribute values is kept during parsing to write them unchanged
when encoding the SignedData anew. For that reason attribute modifications of
already existing SignerInfos may not be included in the newly encoded SignedData.
For that reason you should explicitly call any of the Attribute clearEncoded
method before changing an Attribute (value).
However, not only the encoding of attributes is kept (and written anew), but also the following
components: Certificate(Choices) elements, RevocationInfoChoice elements, and the SignerInfo
fields version, signerIdentifier, signedAttrs, signatureAlgorithm and signature, and each
unsigned attribute and unsigned attribute value. If you do not want to keep the encoding
of these fields (to encode them anew in any case) just call static method keepComponentEncodings
with false
as parameter:
SignedDataInOutStream.setKeepComponentEncodings(false);
SignedDataInOutStream
should be used with an IAIK-JCE version >5.3,
at least an IAIK-JCE version >3.16 is required.
Field Summary |
---|
Fields inherited from class iaik.cms.SignedDataStream |
---|
blockSize_, certSet_, contentType_, crls_, encapContentInfo_, EXPLICIT, IMPLICIT, inputStream_, mode_, securityProvider_, signerInfos_, thisObject_, version_ |
Constructor Summary | |
---|---|
SignedDataInOutStream(java.io.InputStream dataIs,
AlgorithmID[] digestAlgs,
SecurityProvider securityProvider)
Creates a new SignedDataInOutStream from an InputStream holding the content that
has been transmitted by other means and an array specifying the hash
algorithms to be used for digesting. |
|
SignedDataInOutStream(java.io.InputStream is,
java.io.OutputStream out)
Creates a new SignedDataInOutStream . |
|
SignedDataInOutStream(java.io.InputStream is,
java.io.OutputStream out,
AlgorithmID[] additionalDigestAlgs)
Creates a new SignedDataInOutStream . |
|
SignedDataInOutStream(java.io.InputStream is,
java.io.OutputStream out,
AlgorithmID[] additionalDigestAlgs,
SecurityProvider securityProvider)
Creates a new SignedDataInOutStream . |
|
SignedDataInOutStream(java.io.InputStream is,
java.io.OutputStream out,
SecurityProvider securityProvider)
Creates a new SignedDataInOutStream . |
Method Summary | |
---|---|
static void |
setKeepComponentEncodings(boolean keepEncodings)
Decides whether to keep the encodings of some certain SignedData/SignerInfo components during parsing to write them unchanged when encoding the SignedData again. |
void |
setOutputStream(java.io.OutputStream out)
Sets the output stream to which to encode the parsed SignedData again. |
void |
setSDSEncodeListener(SDSEncodeListener sdsEncodeListener)
Sets an SDSEncodeListener for this SignedDataStream, but throws a RuntimeException if an output stream has been set when creating the SignedDataInOutStream object or by calling method setOutputStream . |
ASN1Object |
toASN1Object()
Returns this SignedData as ASN1Object, but throws a RuntimeException if an output stream has been set when creating the SignedDataInOutStream object or by calling method setOutputStream . |
protected ASN1Object |
toASN1Object(int blockSize)
Returns this SignedData as ASN1Object where a constructed OCTET STRING is used for encoding the content, but throws a RuntimeException if an output stream has been set when creating the SignedDataInOutStream object or by calling method setOutputStream . |
void |
write()
Finishes the encoding and writes the certificates, CRLs (if set) and the SignerInfo objects to the stream. |
void |
writeTo(java.io.OutputStream os)
BER encodes and writes the SignedData to the supplied output stream, but throws a RuntimeException if an output stream has been already set when creating the SignedDataInOutStream object or by calling method setOutputStream . |
void |
writeTo(java.io.OutputStream os,
int blockSize)
BER encodes and writes the SignedData to the supplied output stream, but throws a RuntimeException if an output stream has been already set when creating the SignedDataInOutStream object or by calling method setOutputStream . |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Constructor Detail |
---|
public SignedDataInOutStream(java.io.InputStream is, java.io.OutputStream out) throws CMSParsingException, java.io.IOException
SignedDataInOutStream
.
is
- the input stream from which to parse the SignedDataout
- the output stream to which to write the encoded SignedData again
CMSParsingException
- if an error occurs during SignedData parsing
java.io.IOException
- if an I/O error occurs during reading/writingpublic SignedDataInOutStream(java.io.InputStream is, java.io.OutputStream out, AlgorithmID[] additionalDigestAlgs) throws CMSParsingException, java.io.IOException
SignedDataInOutStream
.
is
- the input stream from which to parse the SignedDataout
- the output stream to which to write the encoded SignedData againadditionalDigestAlgs
- any additional digest algorithm ids to be added
to the digestAlgorithms
field
CMSParsingException
- if an error occurs during SignedData parsing
java.io.IOException
- if an I/O error occurs during reading/writingpublic SignedDataInOutStream(java.io.InputStream is, java.io.OutputStream out, SecurityProvider securityProvider) throws CMSParsingException, java.io.IOException
SignedDataInOutStream
.
is
- the input stream from which to parse the SignedDataout
- the output stream to which to write the encoded SignedData againsecurityProvider
- the CMS SecurityProvider to be used for cryptographic
operations
CMSParsingException
- if an error occurs during SignedData parsing
java.io.IOException
- if an I/O error occurs during reading/writingpublic SignedDataInOutStream(java.io.InputStream is, java.io.OutputStream out, AlgorithmID[] additionalDigestAlgs, SecurityProvider securityProvider) throws CMSParsingException, java.io.IOException
SignedDataInOutStream
.
is
- the input stream from which to parse the SignedDataout
- the output stream to which to write the encoded SignedData againadditionalDigestAlgs
- any additional digest algorithm ids to be added
to the digestAlgorithms
fieldsecurityProvider
- the CMS SecurityProvider to be used for cryptographic
operations
CMSParsingException
- if an error occurs during SignedData parsing
java.io.IOException
- if an I/O error occurs during reading/writingpublic SignedDataInOutStream(java.io.InputStream dataIs, AlgorithmID[] digestAlgs, SecurityProvider securityProvider) throws CMSParsingException, java.io.IOException
SignedDataInOutStream
from an InputStream holding the content that
has been transmitted by other means and an array specifying the hash
algorithms to be used for digesting.
Do not use this constructor for supplying the content value
to be signed. This constructor may be used by the recipient for initializing
the digest computation for an already existing explicit SignedDataStream message
where the content data is not included (EXPLICIT
mode). The actual decoding has to be performed by calling
the decode
method just after reading the
data.
Since the main use case of this SignedDataInOutStream
class is to encode the
SignedData again when parsing it method setOutputStream
maybe used to specify the output stream to which to encode the SignedData again.
It is important to call method setOutputStream
before calling method decode
:
// the content data provided by other means: InputStream dataIs = ...; // the digest algorithms AlgorithmID[] digestAlgorithms = ...; // initialize for digest computation: SignedDataInOutStream signedData = new SignedInOutDataStream(dataIs, digestAlgorithms, null); //read the stream thereby updating the hash values: dataIs = signedData.getInputStream(); byte[] buf = new byte[4096]; int r; while ((r = dataIs.read(buf)) > 0) { // do something useful } // set the output stream to which to encode the parsed SignedData again: OutputStream os = ...; signedData.setOutputStream(os); // the stream from which to read the encoded SignedData InputStream signedDataIs = ...; // explicitly perform the decoding signedData.decode(signedDataIs);Note that this constructor is only included to provide the functionality of the same
constructor
of the parent SignedDataStream
class. It requires that
the digest algorithm(s) for an explicit SignedData message have to be known in advance
before actually parsing it. The digestAlgs
field may also contain any
additional digest algorithm(s) that may be required when, e.g., adding a new SignerInfo.
When not knowing the digest algorithms of the to-be-parsed SignedData message in advance
it will be more appropriate to create the SignedDataInOutStream
in the accustomed way
and subsequently call method setInputStream
to provide the
content data received by other means:
// the stream from which to read the encoded SignedData InputStream signedDataIs = ...; // the output stream to which to encode the parsed SignedData again: OutputStream os = ...; SignedDataInOutStream signedData = new SignedInOutDataStream(signedDataIs, os); // in explicit mode explicitly supply the content for hash computation if (signed_data.getMode() == SignedDataStream.EXPLICIT) { // the content data provided by other means: InputStream dataIs = ...; signedData.setInputStream(dataIs); } //read the stream thereby updating the hash values: InputStream dataIs = signedData.getInputStream(); byte[] buf = new byte[4096]; int r; while ((r = dataIs.read(buf)) > 0) { // do something useful } ....
dataIs
- the InputStream supplying the content data which has been transmitted by other meansdigestAlgs
- the digest algorithms used by the participated signers for digesting the
content data and any additional digest algorithms that may be requiredsecurityProvider
- the SecurityProvider to be used for this SignedData object; if null
the default system-wide installed SecurityProvider is used
java.io.IOException
- if there is no implementation for the specified hash algorithm
CMSParsingException
Method Detail |
---|
public static void setKeepComponentEncodings(boolean keepEncodings)
During parsing the encodings of the following components are kept: Certificate(Choices)
elements, RevocationInfoChoice elements, and the SignerInfo fields version, signerIdentifier,
signedAttrs, signatureAlgorithm and signature, and each unsigned attribute and unsigned
attribute value. If you do not want to keep the encoding of these fields (to encode them
anew in any case) just call this method with false
as parameter:
SignedDataInOutStream.setKeepComponentEncodings(false);
keepEncodings
- whether to keep the encodings of certain components during parsing
(default: true
)public void setOutputStream(java.io.OutputStream out)
SignedDataInOutStream
object in explicit mode with the SignedDataInOutStream(InputStream dataIs,
AlgorithmID[] digestAlgs, SecurityProvider securityProvider)
constructor from the
content data and later call method decode
to parse the
SignedData:
// the content data provided by other means: InputStream dataIs = ...; // the digest algorithms AlgorithmID[] digestAlgorithms = ...; // initialize for digest computation: SignedDataInOutStream signedData = new SignedInOutDataStream(dataIs, digestAlgorithms, null); //read the stream thereby updating the hash values: dataIs = signedData.getInputStream(); byte[] buf = new byte[4096]; int r; while ((r = dataIs.read(buf)) > 0) { // do something useful } // set the output stream to which to encode the parsed SignedData again: OutputStream os = ...; signedData.setOutputStream(os); // the stream from which to read the encoded SignedData InputStream signedDataIs = ...; // explicitly perform the decoding signedData.decode(signedDataIs);When using this method in any other case an
IllegalStateException
will be thrown.
out
- the output stream to which to write the newly encoded SignedData
java.lang.IllegalStateException
- if this method is called when SignedData parsing
already has occurredpublic void write() throws java.io.IOException
SignerInfo
objects to the stream.
creating
the SignedDataInOutStream object, it is not required as parameter for the
final write()
method.
Note that in difference to the writeTo
method of class SignedDataStream
method write
already wraps the SignedData into a ContentInfo.
java.io.IOException
- if an I/O error occurs while writing to the streampublic void writeTo(java.io.OutputStream os) throws java.io.IOException
SignedDataInOutStream
object or by calling method setOutputStream
.
In this case method write
has to be used for encoding the
SignedData (again).
writeTo
in class SignedDataStream
os
- the output stream to which this SignedDataStream shall be encoded
java.io.IOException
- if an error occurs when writing to the streampublic void writeTo(java.io.OutputStream os, int blockSize) throws java.io.IOException
SignedDataInOutStream
object or by calling method setOutputStream
.
In this case method write
has to be used for encoding the
SignedData (again).
writeTo
in class SignedDataStream
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 positive
java.io.IOException
- if an error occurs during writing the objectpublic void setSDSEncodeListener(SDSEncodeListener sdsEncodeListener) throws java.security.NoSuchAlgorithmException
SignedDataInOutStream
object or by calling method setOutputStream
.
setSDSEncodeListener
in class SignedDataStream
sdsEncodeListener
- the SDSEncodeListener to be set
if
- the SDSEncodeListener announces any not supported
digest algorithms to be used
java.security.NoSuchAlgorithmException
SDSEncodeListener
public ASN1Object toASN1Object() throws CMSException
SignedDataInOutStream
object or by calling method setOutputStream
.
toASN1Object
in interface ContentStream
toASN1Object
in class SignedDataStream
CMSException
- if the ASN1Object could not be createdprotected ASN1Object toASN1Object(int blockSize) throws CMSException
SignedDataInOutStream
object or by calling method setOutputStream
.
toASN1Object
in class SignedDataStream
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
|
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 |