All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.cms.CMSAuthenticatedDataParser Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified.

There is a newer version: 2.0.7
Show newest version
package org.bouncycastle.cms;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1OctetStringParser;
import org.bouncycastle.asn1.ASN1SequenceParser;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.ASN1SetParser;
import org.bouncycastle.asn1.BERTags;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.AuthenticatedDataParser;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.ContentInfoParser;
import org.bouncycastle.asn1.cms.OriginatorInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Arrays;

/**
 * Parsing class for an CMS Authenticated Data object from an input stream.
 * 

* Note: that because we are in a streaming mode only one recipient can be tried and it is important * that the methods on the parser are called in the appropriate order. *

*

* Example of use - assuming the first recipient matches the private key we have. *

 *      CMSAuthenticatedDataParser     ad = new CMSAuthenticatedDataParser(inputStream);
 *
 *      RecipientInformationStore  recipients = ad.getRecipientInfos();
 *
 *      Collection  c = recipients.getRecipients();
 *      Iterator    it = c.iterator();
 *
 *      if (it.hasNext())
 *      {
 *          RecipientInformation   recipient = (RecipientInformation)it.next();
 *
 *          CMSTypedStream recData = recipient.getContentStream(new JceKeyTransAuthenticatedRecipient(privateKey).setProvider("BC"));
 *
 *          processDataStream(recData.getContentStream());
 *
 *          if (!Arrays.equals(ad.getMac(), recipient.getMac())
 *          {
 *              System.err.println("Data corrupted!!!!");
 *          }
 *      }
 *  
* Note: this class does not introduce buffering - if you are processing large files you should create * the parser with: *
 *          CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
 *  
* where bufSize is a suitably large buffer size. */ public class CMSAuthenticatedDataParser extends CMSContentInfoParser { RecipientInformationStore recipientInfoStore; AuthenticatedDataParser authData; private AlgorithmIdentifier macAlg; private byte[] mac; private AttributeTable authAttrs; private ASN1Set authAttrSet; private AttributeTable unauthAttrs; private boolean authAttrNotRead; private boolean unauthAttrNotRead; private OriginatorInformation originatorInfo; public CMSAuthenticatedDataParser( byte[] envelopedData) throws CMSException, IOException { this(new ByteArrayInputStream(envelopedData)); } public CMSAuthenticatedDataParser( byte[] envelopedData, DigestCalculatorProvider digestCalculatorProvider) throws CMSException, IOException { this(new ByteArrayInputStream(envelopedData), digestCalculatorProvider); } public CMSAuthenticatedDataParser( InputStream envelopedData) throws CMSException, IOException { this(envelopedData, null); } public CMSAuthenticatedDataParser( InputStream envelopedData, DigestCalculatorProvider digestCalculatorProvider) throws CMSException, IOException { super(envelopedData); this.authAttrNotRead = true; this.authData = new AuthenticatedDataParser((ASN1SequenceParser)_contentInfo.getContent(BERTags.SEQUENCE)); // TODO Validate version? //ASN1Integer version = this.authData.getVersion(); OriginatorInfo info = authData.getOriginatorInfo(); if (info != null) { this.originatorInfo = new OriginatorInformation(info); } // // read the recipients // ASN1Set recipientInfos = ASN1Set.getInstance(authData.getRecipientInfos().toASN1Primitive()); this.macAlg = authData.getMacAlgorithm(); // // build the RecipientInformationStore // AlgorithmIdentifier digestAlgorithm = authData.getDigestAlgorithm(); if (digestAlgorithm != null) { if (digestCalculatorProvider == null) { throw new CMSException("a digest calculator provider is required if authenticated attributes are present"); } // // read the authenticated content info // ContentInfoParser data = authData.getEncapsulatedContentInfo(); CMSReadable readable = new CMSProcessableInputStream( ((ASN1OctetStringParser)data.getContent(BERTags.OCTET_STRING)).getOctetStream()); try { CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(digestAlgorithm), readable); this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable, new AuthAttributesProvider() { public ASN1Set getAuthAttributes() { try { return getAuthAttrSet(); } catch (IOException e) { throw new IllegalStateException("can't parse authenticated attributes!"); } } }); } catch (OperatorCreationException e) { throw new CMSException("unable to create digest calculator: " + e.getMessage(), e); } } else { // // read the authenticated content info // ContentInfoParser data = authData.getEncapsulatedContentInfo(); CMSReadable readable = new CMSProcessableInputStream( ((ASN1OctetStringParser)data.getContent(BERTags.OCTET_STRING)).getOctetStream()); CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSAuthenticatedSecureReadable(this.macAlg, readable); this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable); } } /** * Return the originator information associated with this message if present. * * @return OriginatorInformation, null if not present. */ public OriginatorInformation getOriginatorInfo() { return originatorInfo; } /** * Return the MAC algorithm details for the MAC associated with the data in this object. * * @return AlgorithmIdentifier representing the MAC algorithm. */ public AlgorithmIdentifier getMacAlgorithm() { return macAlg; } /** * return the object identifier for the mac algorithm. */ public String getMacAlgOID() { return macAlg.getAlgorithm().toString(); } /** * return the ASN.1 encoded encryption algorithm parameters, or null if * there aren't any. */ public byte[] getMacAlgParams() { try { return encodeObj(macAlg.getParameters()); } catch (Exception e) { throw new RuntimeException("exception getting encryption parameters " + e); } } /** * return a store of the intended recipients for this message */ public RecipientInformationStore getRecipientInfos() { return recipientInfoStore; } public byte[] getMac() throws IOException { if (mac == null) { getAuthAttrs(); mac = authData.getMac().getOctets(); } return Arrays.clone(mac); } private ASN1Set getAuthAttrSet() throws IOException { if (authAttrs == null && authAttrNotRead) { ASN1SetParser set = authData.getAuthAttrs(); if (set != null) { authAttrSet = (ASN1Set)set.toASN1Primitive(); } authAttrNotRead = false; } return authAttrSet; } /** * return a table of the unauthenticated attributes indexed by * the OID of the attribute. * @exception java.io.IOException */ public AttributeTable getAuthAttrs() throws IOException { if (authAttrs == null && authAttrNotRead) { ASN1Set set = getAuthAttrSet(); if (set != null) { authAttrs = new AttributeTable(set); } } return authAttrs; } /** * return a table of the unauthenticated attributes indexed by * the OID of the attribute. * @exception java.io.IOException */ public AttributeTable getUnauthAttrs() throws IOException { if (unauthAttrs == null && unauthAttrNotRead) { ASN1SetParser set = authData.getUnauthAttrs(); unauthAttrNotRead = false; if (set != null) { ASN1EncodableVector v = new ASN1EncodableVector(); ASN1Encodable o; while ((o = set.readObject()) != null) { ASN1SequenceParser seq = (ASN1SequenceParser)o; v.add(seq.toASN1Primitive()); } unauthAttrs = new AttributeTable(new DERSet(v)); } } return unauthAttrs; } private byte[] encodeObj( ASN1Encodable obj) throws IOException { if (obj != null) { return obj.toASN1Primitive().getEncoded(); } return null; } /** * This will only be valid after the content has been read. * * @return the contents of the messageDigest attribute, if available. Null if not present. */ public byte[] getContentDigest() { if (authAttrs != null) { return ASN1OctetString.getInstance(authAttrs.get(CMSAttributes.messageDigest).getAttrValues().getObjectAt(0)).getOctets(); } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy