package org.bouncycastle.asn1.cms; import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.BERSequence; import org.bouncycastle.asn1.BERTaggedObject; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.DERObject; import org.bouncycastle.asn1.DERTaggedObject; /** * a signed data object. */ public class SignedData extends ASN1Encodable { private DERInteger version; private ASN1Set digestAlgorithms; private ContentInfo contentInfo; private ASN1Set certificates; private ASN1Set crls; private ASN1Set signerInfos; private boolean certBer; private boolean crlsBer; public static SignedData getInstance( Object o) { if (o instanceof SignedData) { return (SignedData)o; } else if (o instanceof ASN1Sequence) { return new SignedData((ASN1Sequence)o); } throw new IllegalArgumentException("unknown object in factory"); } public SignedData( ASN1Set digestAlgorithms, ContentInfo contentInfo, ASN1Set certificates, ASN1Set crls, ASN1Set signerInfos) { if (contentInfo.getContentType().equals(CMSObjectIdentifiers.data)) { // // we should also be looking for attribute certificates here, // later. // Enumeration e = signerInfos.getObjects(); boolean v3Found = false; while (e.hasMoreElements()) { SignerInfo s = SignerInfo.getInstance(e.nextElement()); if (s.getVersion().getValue().intValue() == 3) { v3Found = true; } } if (v3Found) { this.version = new DERInteger(3); } else { this.version = new DERInteger(1); } } else { this.version = new DERInteger(3); } this.digestAlgorithms = digestAlgorithms; this.contentInfo = contentInfo; this.certificates = certificates; this.crls = crls; this.signerInfos = signerInfos; } public SignedData( ASN1Sequence seq) { Enumeration e = seq.getObjects(); version = (DERInteger)e.nextElement(); digestAlgorithms = ((ASN1Set)e.nextElement()); contentInfo = ContentInfo.getInstance(e.nextElement()); while (e.hasMoreElements()) { DERObject o = (DERObject)e.nextElement(); // // an interesting feature of SignedData is that there appear // to be varying implementations... // for the moment we ignore anything which doesn't fit. // if (o instanceof ASN1TaggedObject) { ASN1TaggedObject tagged = (ASN1TaggedObject)o; switch (tagged.getTagNo()) { case 0: certBer = tagged instanceof BERTaggedObject; certificates = ASN1Set.getInstance(tagged, false); break; case 1: crlsBer = tagged instanceof BERTaggedObject; crls = ASN1Set.getInstance(tagged, false); break; default: throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo()); } } else { signerInfos = (ASN1Set)o; } } } public DERInteger getVersion() { return version; } public ASN1Set getDigestAlgorithms() { return digestAlgorithms; } public ContentInfo getEncapContentInfo() { return contentInfo; } public ASN1Set getCertificates() { return certificates; } public ASN1Set getCRLs() { return crls; } public ASN1Set getSignerInfos() { return signerInfos; } /** * Produce an object suitable for an ASN1OutputStream. * <pre> * SignedData ::= SEQUENCE { * version CMSVersion, * digestAlgorithms DigestAlgorithmIdentifiers, * encapContentInfo EncapsulatedContentInfo, * certificates [0] IMPLICIT CertificateSet OPTIONAL, * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, * signerInfos SignerInfos * } * </pre> */ public DERObject toASN1Object() { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(version); v.add(digestAlgorithms); v.add(contentInfo); if (certificates != null) { if (certBer) { v.add(new BERTaggedObject(false, 0, certificates)); } else { v.add(new DERTaggedObject(false, 0, certificates)); } } if (crls != null) { if (crlsBer) { v.add(new BERTaggedObject(false, 1, crls)); } else { v.add(new DERTaggedObject(false, 1, crls)); } } v.add(signerInfos); return new BERSequence(v); } }