Java tutorial
package org.bouncycastle.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BEROctetStringGenerator; import org.bouncycastle.asn1.BERSet; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.OtherRevocationInfoFormat; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.ocsp.OCSPResponse; import org.bouncycastle.asn1.ocsp.OCSPResponseStatus; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.X509AttributeCertificateHolder; import org.bouncycastle.cert.X509CRLHolder; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.operator.DigestCalculator; import org.bouncycastle.util.Store; import org.bouncycastle.util.Strings; import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.TeeInputStream; import org.bouncycastle.util.io.TeeOutputStream; class CMSUtils { private static final Set<String> des = new HashSet<String>(); private static final Set mqvAlgs = new HashSet(); private static final Set ecAlgs = new HashSet(); private static final Set gostAlgs = new HashSet(); static { des.add("DES"); des.add("DESEDE"); des.add(OIWObjectIdentifiers.desCBC.getId()); des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); des.add(PKCSObjectIdentifiers.des_EDE3_CBC.getId()); des.add(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId()); mqvAlgs.add(X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme); mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha224kdf_scheme); mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha256kdf_scheme); mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha384kdf_scheme); mqvAlgs.add(SECObjectIdentifiers.mqvSinglePass_sha512kdf_scheme); ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_cofactorDH_sha1kdf_scheme); ecAlgs.add(X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme); ecAlgs.add(SECObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme); gostAlgs.add(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_ESDH); gostAlgs.add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_256); gostAlgs.add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_512); } static boolean isMQV(ASN1ObjectIdentifier algorithm) { return mqvAlgs.contains(algorithm); } static boolean isEC(ASN1ObjectIdentifier algorithm) { return ecAlgs.contains(algorithm); } static boolean isGOST(ASN1ObjectIdentifier algorithm) { return gostAlgs.contains(algorithm); } static boolean isRFC2631(ASN1ObjectIdentifier algorithm) { return algorithm.equals(PKCSObjectIdentifiers.id_alg_ESDH) || algorithm.equals(PKCSObjectIdentifiers.id_alg_SSDH); } static boolean isDES(String algorithmID) { String name = Strings.toUpperCase(algorithmID); return des.contains(name); } static boolean isEquivalent(AlgorithmIdentifier algId1, AlgorithmIdentifier algId2) { if (algId1 == null || algId2 == null) { return false; } if (!algId1.getAlgorithm().equals(algId2.getAlgorithm())) { return false; } ASN1Encodable params1 = algId1.getParameters(); ASN1Encodable params2 = algId2.getParameters(); if (params1 != null) { return params1.equals(params2) || (params1.equals(DERNull.INSTANCE) && params2 == null); } return params2 == null || params2.equals(DERNull.INSTANCE); } static ContentInfo readContentInfo(byte[] input) throws CMSException { // enforce limit checking as from a byte array return readContentInfo(new ASN1InputStream(input)); } static ContentInfo readContentInfo(InputStream input) throws CMSException { // enforce some limit checking return readContentInfo(new ASN1InputStream(input)); } static List getCertificatesFromStore(Store certStore) throws CMSException { List certs = new ArrayList(); try { for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();) { X509CertificateHolder c = (X509CertificateHolder) it.next(); certs.add(c.toASN1Structure()); } return certs; } catch (ClassCastException e) { throw new CMSException("error processing certs", e); } } static List getAttributeCertificatesFromStore(Store attrStore) throws CMSException { List certs = new ArrayList(); try { for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();) { X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder) it.next(); certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure())); } return certs; } catch (ClassCastException e) { throw new CMSException("error processing certs", e); } } static List getCRLsFromStore(Store crlStore) throws CMSException { List crls = new ArrayList(); try { for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();) { Object rev = it.next(); if (rev instanceof X509CRLHolder) { X509CRLHolder c = (X509CRLHolder) rev; crls.add(c.toASN1Structure()); } else if (rev instanceof OtherRevocationInfoFormat) { OtherRevocationInfoFormat infoFormat = OtherRevocationInfoFormat.getInstance(rev); validateInfoFormat(infoFormat); crls.add(new DERTaggedObject(false, 1, infoFormat)); } else if (rev instanceof ASN1TaggedObject) { crls.add(rev); } } return crls; } catch (ClassCastException e) { throw new CMSException("error processing certs", e); } } private static void validateInfoFormat(OtherRevocationInfoFormat infoFormat) { if (CMSObjectIdentifiers.id_ri_ocsp_response.equals(infoFormat.getInfoFormat())) { OCSPResponse resp = OCSPResponse.getInstance(infoFormat.getInfo()); if (resp.getResponseStatus().getValue().intValue() != OCSPResponseStatus.SUCCESSFUL) { throw new IllegalArgumentException("cannot add unsuccessful OCSP response to CMS SignedData"); } } } static Collection getOthersFromStore(ASN1ObjectIdentifier otherRevocationInfoFormat, Store otherRevocationInfos) { List others = new ArrayList(); for (Iterator it = otherRevocationInfos.getMatches(null).iterator(); it.hasNext();) { ASN1Encodable info = (ASN1Encodable) it.next(); OtherRevocationInfoFormat infoFormat = new OtherRevocationInfoFormat(otherRevocationInfoFormat, info); validateInfoFormat(infoFormat); others.add(new DERTaggedObject(false, 1, infoFormat)); } return others; } static ASN1Set createBerSetFromList(List derObjects) { ASN1EncodableVector v = new ASN1EncodableVector(); for (Iterator it = derObjects.iterator(); it.hasNext();) { v.add((ASN1Encodable) it.next()); } return new BERSet(v); } static ASN1Set createDerSetFromList(List derObjects) { ASN1EncodableVector v = new ASN1EncodableVector(); for (Iterator it = derObjects.iterator(); it.hasNext();) { v.add((ASN1Encodable) it.next()); } return new DERSet(v); } static OutputStream createBEROctetOutputStream(OutputStream s, int tagNo, boolean isExplicit, int bufferSize) throws IOException { BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit); if (bufferSize != 0) { return octGen.getOctetOutputStream(new byte[bufferSize]); } return octGen.getOctetOutputStream(); } private static ContentInfo readContentInfo(ASN1InputStream in) throws CMSException { try { ContentInfo info = ContentInfo.getInstance(in.readObject()); if (info == null) { throw new CMSException("No content found."); } return info; } catch (IOException e) { throw new CMSException("IOException reading content.", e); } catch (ClassCastException e) { throw new CMSException("Malformed content.", e); } catch (IllegalArgumentException e) { throw new CMSException("Malformed content.", e); } } public static byte[] streamToByteArray(InputStream in) throws IOException { return Streams.readAll(in); } public static byte[] streamToByteArray(InputStream in, int limit) throws IOException { return Streams.readAllLimited(in, limit); } static InputStream attachDigestsToInputStream(Collection digests, InputStream s) { InputStream result = s; Iterator it = digests.iterator(); while (it.hasNext()) { DigestCalculator digest = (DigestCalculator) it.next(); result = new TeeInputStream(result, digest.getOutputStream()); } return result; } static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s) { OutputStream result = s; Iterator it = signers.iterator(); while (it.hasNext()) { SignerInfoGenerator signerGen = (SignerInfoGenerator) it.next(); result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream()); } return result; } static OutputStream getSafeOutputStream(OutputStream s) { return s == null ? new NullOutputStream() : s; } static OutputStream getSafeTeeOutputStream(OutputStream s1, OutputStream s2) { return s1 == null ? getSafeOutputStream(s2) : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(s1, s2); } }