package org.bouncycastle.cms;

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.ASN1Set;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.AuthenticatedData;
import org.bouncycastle.asn1.cms.CMSAlgorithmProtection;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Encodable;

containing class for an CMS Authenticated Data object
/** * containing class for an CMS Authenticated Data object */
public class CMSAuthenticatedData implements Encodable { RecipientInformationStore recipientInfoStore; ContentInfo contentInfo; private AlgorithmIdentifier macAlg; private ASN1Set authAttrs; private ASN1Set unauthAttrs; private byte[] mac; private OriginatorInformation originatorInfo; public CMSAuthenticatedData( byte[] authData) throws CMSException { this(CMSUtils.readContentInfo(authData)); } public CMSAuthenticatedData( byte[] authData, DigestCalculatorProvider digestCalculatorProvider) throws CMSException { this(CMSUtils.readContentInfo(authData), digestCalculatorProvider); } public CMSAuthenticatedData( InputStream authData) throws CMSException { this(CMSUtils.readContentInfo(authData)); } public CMSAuthenticatedData( InputStream authData, DigestCalculatorProvider digestCalculatorProvider) throws CMSException { this(CMSUtils.readContentInfo(authData), digestCalculatorProvider); } public CMSAuthenticatedData( ContentInfo contentInfo) throws CMSException { this(contentInfo, null); } public CMSAuthenticatedData( ContentInfo contentInfo, DigestCalculatorProvider digestCalculatorProvider) throws CMSException { this.contentInfo = contentInfo; AuthenticatedData authData = AuthenticatedData.getInstance(contentInfo.getContent()); if (authData.getOriginatorInfo() != null) { this.originatorInfo = new OriginatorInformation(authData.getOriginatorInfo()); } // // read the recipients // ASN1Set recipientInfos = authData.getRecipientInfos(); this.macAlg = authData.getMacAlgorithm(); this.authAttrs = authData.getAuthAttrs(); this.mac = authData.getMac().getOctets(); this.unauthAttrs = authData.getUnauthAttrs(); // // read the authenticated content info // ContentInfo encInfo = authData.getEncapsulatedContentInfo(); CMSReadable readable = new CMSProcessableByteArray( ASN1OctetString.getInstance(encInfo.getContent()).getOctets()); // // build the RecipientInformationStore // if (authAttrs != null) { if (digestCalculatorProvider == null) { throw new CMSException("a digest calculator provider is required if authenticated attributes are present"); } AttributeTable table = new AttributeTable(authAttrs); ASN1EncodableVector protectionAttributes = table.getAll(CMSAttributes.cmsAlgorithmProtect); if (protectionAttributes.size() > 1) { throw new CMSException("Only one instance of a cmsAlgorithmProtect attribute can be present"); } if (protectionAttributes.size() > 0) { Attribute attr = Attribute.getInstance(protectionAttributes.get(0)); if (attr.getAttrValues().size() != 1) { throw new CMSException("A cmsAlgorithmProtect attribute MUST contain exactly one value"); } CMSAlgorithmProtection algorithmProtection = CMSAlgorithmProtection.getInstance(attr.getAttributeValues()[0]); if (!CMSUtils.isEquivalent(algorithmProtection.getDigestAlgorithm(), authData.getDigestAlgorithm())) { throw new CMSException("CMS Algorithm Identifier Protection check failed for digestAlgorithm"); } if (!CMSUtils.isEquivalent(algorithmProtection.getMacAlgorithm(), macAlg)) { throw new CMSException("CMS Algorithm Identifier Protection check failed for macAlgorithm"); } } try { CMSSecureReadable secureReadable = new CMSEnvelopedHelper.CMSDigestAuthenticatedSecureReadable(digestCalculatorProvider.get(authData.getDigestAlgorithm()), readable); this.recipientInfoStore = CMSEnvelopedHelper.buildRecipientInformationStore(recipientInfos, this.macAlg, secureReadable, new AuthAttributesProvider() { public ASN1Set getAuthAttributes() { return authAttrs; } }); } catch (OperatorCreationException e) { throw new CMSException("unable to create digest calculator: " + e.getMessage(), e); } } else { 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.
Returns:OriginatorInformation, null if not present.
/** * Return the originator information associated with this message if present. * * @return OriginatorInformation, null if not present. */
public OriginatorInformation getOriginatorInfo() { return originatorInfo; } public byte[] getMac() { return Arrays.clone(mac); } private byte[] encodeObj( ASN1Encodable obj) throws IOException { if (obj != null) { return obj.toASN1Primitive().getEncoded(); } return null; }
Return the MAC algorithm details for the MAC associated with the data in this object.
Returns:AlgorithmIdentifier representing the MAC algorithm.
/** * 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 content MAC algorithm.
/** * return the object identifier for the content MAC algorithm. */
public String getMacAlgOID() { return macAlg.getAlgorithm().getId(); }
return the ASN.1 encoded MAC algorithm parameters, or null if there aren't any.
/** * return the ASN.1 encoded MAC 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
/** * return a store of the intended recipients for this message */
public RecipientInformationStore getRecipientInfos() { return recipientInfoStore; }
return the ContentInfo
Deprecated:use toASN1Structure()
/** * return the ContentInfo * @deprecated use toASN1Structure() */
public ContentInfo getContentInfo() { return contentInfo; }
return the ContentInfo
/** * return the ContentInfo */
public ContentInfo toASN1Structure() { return contentInfo; }
return a table of the digested attributes indexed by the OID of the attribute.
/** * return a table of the digested attributes indexed by * the OID of the attribute. */
public AttributeTable getAuthAttrs() { if (authAttrs == null) { return null; } return new AttributeTable(authAttrs); }
return a table of the undigested attributes indexed by the OID of the attribute.
/** * return a table of the undigested attributes indexed by * the OID of the attribute. */
public AttributeTable getUnauthAttrs() { if (unauthAttrs == null) { return null; } return new AttributeTable(unauthAttrs); }
return the ASN.1 encoded representation of this object.
/** * return the ASN.1 encoded representation of this object. */
public byte[] getEncoded() throws IOException { return contentInfo.getEncoded(); } public byte[] getContentDigest() { if (authAttrs != null) { return ASN1OctetString.getInstance(getAuthAttrs().get(CMSAttributes.messageDigest).getAttrValues().getObjectAt(0)).getOctets(); } return null; } }