package org.spongycastle.pkcs; import java.io.IOException; import org.spongycastle.asn1.ASN1OctetString; import org.spongycastle.asn1.ASN1Sequence; import org.spongycastle.asn1.pkcs.ContentInfo; import org.spongycastle.asn1.pkcs.MacData; import org.spongycastle.asn1.pkcs.PKCS12PBEParams; import org.spongycastle.asn1.pkcs.Pfx; import org.spongycastle.asn1.x509.AlgorithmIdentifier; import org.spongycastle.util.Arrays; /** * A holding class for the PKCS12 Pfx structure. */ public class PKCS12PfxPdu { private Pfx pfx; public PKCS12PfxPdu(Pfx pfx) { this.pfx = pfx; } /** * Return the content infos in the AuthenticatedSafe contained in this Pfx. * * @return an array of ContentInfo. */ public ContentInfo[] getContentInfos() { ASN1Sequence seq = ASN1Sequence.getInstance(ASN1OctetString.getInstance(this.pfx.getAuthSafe().getContent()).getOctets()); ContentInfo[] content = new ContentInfo[seq.size()]; for (int i = 0; i != seq.size(); i++) { content[i] = ContentInfo.getInstance(seq.getObjectAt(i)); } return content; } /** * Return whether or not there is MAC attached to this file. * * @return true if there is, false otherwise. */ public boolean hasMac() { return pfx.getMacData() != null; } /** * Verify the MacData attached to the PFX is consistent with what is expected. * * @param macCalcProviderBuilder provider builder for the calculator for the MAC * @param password password to use * @return true if mac data is valid, false otherwise. * @throws PKCSException if there is a problem evaluating the MAC. * @throws IllegalStateException if no MAC is actually present */ public boolean isMacValid(PKCS12MacCalculatorBuilderProvider macCalcProviderBuilder, char[] password) throws PKCSException { if (hasMac()) { MacData pfxmData = pfx.getMacData(); MacDataGenerator mdGen = new MacDataGenerator(macCalcProviderBuilder.get(new AlgorithmIdentifier(pfxmData.getMac().getAlgorithmId().getAlgorithm(), new PKCS12PBEParams(pfxmData.getSalt(), pfxmData.getIterationCount().intValue())))); try { MacData mData = mdGen.build( password, ASN1OctetString.getInstance(pfx.getAuthSafe().getContent()).getOctets()); return Arrays.constantTimeAreEqual(mData.getEncoded(), pfx.getMacData().getEncoded()); } catch (IOException e) { throw new PKCSException("unable to process AuthSafe: " + e.getMessage()); } } throw new IllegalStateException("no MAC present on PFX"); } /** * Return the underlying ASN.1 object. * * @return a Pfx object. */ public Pfx toASN1Structure() { return pfx; } }