1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72:
73:
79: public class PKCS7SignedData
80: {
81: private static final Logger log = Logger.getLogger(PKCS7SignedData.class.getName());
82:
83: public static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
84:
85: private BigInteger version;
86: private Set digestAlgorithms;
87: private OID contentType;
88: private byte[] content;
89: private Certificate[] certificates;
90: private CRL[] crls;
91: private Set signerInfos;
92:
93: public PKCS7SignedData(InputStream in)
94: throws CRLException, CertificateException, IOException
95: {
96: this(new BERReader(in));
97: }
98:
99:
152: public PKCS7SignedData(BERReader ber)
153: throws CRLException, CertificateException, IOException
154: {
155: CertificateFactory x509 = CertificateFactory.getInstance("X509");
156: DERValue val = ber.read();
157: if (!val.isConstructed())
158: throw new BEREncodingException("malformed ContentInfo");
159:
160: val = ber.read();
161: if (val.getTag() != BER.OBJECT_IDENTIFIER)
162: throw new BEREncodingException("malformed ContentType");
163:
164: if (!PKCS7_SIGNED_DATA.equals(val.getValue()))
165: throw new BEREncodingException("content is not SignedData");
166:
167: val = ber.read();
168: if (val.getTag() != 0)
169: throw new BEREncodingException("malformed Content");
170:
171: val = ber.read();
172: if (!val.isConstructed())
173: throw new BEREncodingException("malformed SignedData");
174:
175: if (Configuration.DEBUG)
176: log.fine("SignedData: " + val);
177:
178: val = ber.read();
179: if (val.getTag() != BER.INTEGER)
180: throw new BEREncodingException("expecting Version");
181: version = (BigInteger) val.getValue();
182: if (Configuration.DEBUG)
183: log.fine(" Version: " + version);
184:
185: digestAlgorithms = new HashSet();
186: val = ber.read();
187: if (!val.isConstructed())
188: throw new BEREncodingException("malformed DigestAlgorithmIdentifiers");
189: if (Configuration.DEBUG)
190: log.fine(" DigestAlgorithmIdentifiers: " + val);
191: int count = 0;
192: DERValue val2 = ber.read();
193: while (val2 != BER.END_OF_SEQUENCE &&
194: (val.getLength() > 0 && val.getLength() > count))
195: {
196: if (!val2.isConstructed())
197: throw new BEREncodingException("malformed AlgorithmIdentifier");
198: if (Configuration.DEBUG)
199: log.fine(" AlgorithmIdentifier: " + val2);
200: count += val2.getEncodedLength();
201: val2 = ber.read();
202: if (val2.getTag() != BER.OBJECT_IDENTIFIER)
203: throw new BEREncodingException("malformed AlgorithmIdentifier");
204: if (Configuration.DEBUG)
205: log.fine(" digestAlgorithmIdentifiers OID: " + val2.getValue());
206: List algId = new ArrayList(2);
207: algId.add(val2.getValue());
208: val2 = ber.read();
209: if (val2 != BER.END_OF_SEQUENCE)
210: {
211: count += val2.getEncodedLength();
212: if (val2.getTag() == BER.NULL)
213: algId.add(null);
214: else
215: algId.add(val2.getEncoded());
216:
217: if (val2.isConstructed())
218: ber.skip(val2.getLength());
219:
220: if (BERValue.isIndefinite(val))
221: val2 = ber.read();
222: }
223: else
224: algId.add(null);
225:
226: if (Configuration.DEBUG)
227: {
228: log.fine(" digestAlgorithmIdentifiers params: ");
229: log.fine(Util.dumpString((byte[]) algId.get(1),
230: " digestAlgorithmIdentifiers params: "));
231: }
232: digestAlgorithms.add(algId);
233: }
234:
235: val = ber.read();
236: if (!val.isConstructed())
237: throw new BEREncodingException("malformed ContentInfo");
238: if (Configuration.DEBUG)
239: log.fine(" ContentInfo: " + val);
240: val2 = ber.read();
241: if (val2.getTag() != BER.OBJECT_IDENTIFIER)
242: throw new BEREncodingException("malformed ContentType");
243:
244: contentType = (OID) val2.getValue();
245: if (Configuration.DEBUG)
246: log.fine(" ContentType OID: " + contentType);
247: if (BERValue.isIndefinite(val)
248: || (val.getLength() > 0 && val.getLength() > val2.getEncodedLength()))
249: {
250: val2 = ber.read();
251: if (val2 != BER.END_OF_SEQUENCE)
252: {
253: content = val2.getEncoded();
254: if (BERValue.isIndefinite(val))
255: val2 = ber.read();
256: }
257: }
258: if (Configuration.DEBUG)
259: {
260: log.fine(" Content: ");
261: log.fine(Util.dumpString(content, " Content: "));
262: }
263: val = ber.read();
264: if (val.getTag() == 0)
265: {
266: if (!val.isConstructed())
267: throw new BEREncodingException("malformed ExtendedCertificatesAndCertificates");
268: if (Configuration.DEBUG)
269: log.fine(" ExtendedCertificatesAndCertificates: " + val);
270: count = 0;
271: val2 = ber.read();
272: List certs = new LinkedList();
273: while (val2 != BER.END_OF_SEQUENCE &&
274: (val.getLength() > 0 && val.getLength() > count))
275: {
276: Certificate cert =
277: x509.generateCertificate(new ByteArrayInputStream(val2.getEncoded()));
278: if (Configuration.DEBUG)
279: log.fine(" Certificate: " + cert);
280: certs.add(cert);
281: count += val2.getEncodedLength();
282: ber.skip(val2.getLength());
283: if (BERValue.isIndefinite(val) || val.getLength() > count)
284: val2 = ber.read();
285: }
286: certificates = (Certificate[]) certs.toArray(new Certificate[certs.size()]);
287: val = ber.read();
288: }
289:
290: if (val.getTag() == 1)
291: {
292: if (!val.isConstructed())
293: throw new BEREncodingException("malformed CertificateRevocationLists");
294: if (Configuration.DEBUG)
295: log.fine(" CertificateRevocationLists: " + val);
296: count = 0;
297: val2 = ber.read();
298: List crls = new LinkedList();
299: while (val2 != BER.END_OF_SEQUENCE &&
300: (val.getLength() > 0 && val.getLength() > count))
301: {
302: CRL crl = x509.generateCRL(new ByteArrayInputStream(val2.getEncoded()));
303: if (Configuration.DEBUG)
304: log.fine(" CRL: " + crl);
305: crls.add(crl);
306: count += val2.getEncodedLength();
307: ber.skip(val2.getLength());
308: if (BERValue.isIndefinite(val) || val.getLength() > count)
309: val2 = ber.read();
310: }
311: this.crls = (CRL[]) crls.toArray(new CRL[crls.size()]);
312: val = ber.read();
313: }
314:
315: signerInfos = new HashSet();
316: if (!val.isConstructed())
317: throw new BEREncodingException("malformed SignerInfos");
318: if (Configuration.DEBUG)
319: log.fine(" SignerInfos: " + val);
320:
321:
322:
323:
324: while (true)
325: {
326: int i = ber.peek();
327: if (i == 0 || i == -1)
328: break;
329: signerInfos.add(new SignerInfo(ber));
330: }
331: }
332:
333:
351: public PKCS7SignedData(Set digestAlgorithms, PKCS7Data data,
352: Certificate[] certificates, X509CRL[] crls,
353: Set signerInfos)
354: {
355: super();
356:
357: this.version = BigInteger.ONE;
358: this.digestAlgorithms = digestAlgorithms;
359: this.contentType = PKCS7_SIGNED_DATA;
360: this.content = data == null ? null : data.getEncoded();
361: this.certificates = certificates;
362: this.crls = crls;
363: this.signerInfos = signerInfos;
364: }
365:
366: public BigInteger getVersion()
367: {
368: return version;
369: }
370:
371: public Certificate[] getCertificates()
372: {
373: return (certificates != null ? (Certificate[]) certificates.clone()
374: : null);
375: }
376:
377: public OID getContentType()
378: {
379: return contentType;
380: }
381:
382: public byte[] getContent()
383: {
384: return (content != null ? (byte[]) content.clone() : null);
385: }
386:
387: public Set getDigestAlgorithms()
388: {
389:
390: return Collections.unmodifiableSet(digestAlgorithms);
391: }
392:
393: public Set getSignerInfos()
394: {
395: Set copy = new HashSet();
396: for (Iterator it = signerInfos.iterator(); it.hasNext(); )
397: copy.add(it.next());
398: return Collections.unmodifiableSet(copy);
399: }
400:
401:
412: public void encode(OutputStream out) throws IOException, CRLException,
413: CertificateEncodingException
414: {
415: DERValue derVersion = new DERValue(DER.INTEGER, version);
416:
417: DERValue derDigestAlgorithms = new DERValue(DER.CONSTRUCTED | DER.SET,
418: digestAlgorithms);
419:
420: DERValue derContentType = new DERValue(DER.OBJECT_IDENTIFIER,
421: PKCS7Data.PKCS7_DATA);
422: ArrayList contentInfo = new ArrayList(2);
423: contentInfo.add(derContentType);
424: if (content == null)
425: contentInfo.add(new DERValue(DER.NULL, null));
426: else
427: contentInfo.add(content);
428:
429: DERValue derContentInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
430: contentInfo);
431:
432: ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
433: for (int i = 0; i < certificates.length; i++)
434: baos.write(certificates[i].getEncoded());
435:
436: baos.flush();
437: byte[] b = baos.toByteArray();
438: DERValue derExtendedCertificatesAndCertificates =
439: new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0, b.length, b, null);
440:
441: DERValue derCertificateRevocationLists = null;
442: if (crls != null && crls.length > 0)
443: {
444: baos.reset();
445: for (int i = 0; i < crls.length; i++)
446: baos.write(((X509CRL) crls[i]).getEncoded());
447:
448: baos.flush();
449: byte[] b2 = baos.toByteArray();
450: derCertificateRevocationLists =
451: new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 1, b2.length, b2, null);
452: }
453:
454: baos.reset();
455: for (Iterator it = signerInfos.iterator(); it.hasNext();)
456: {
457: SignerInfo signerInfo = (SignerInfo) it.next();
458: signerInfo.encode(baos);
459: }
460: baos.flush();
461: byte[] b3 = baos.toByteArray();
462: DERValue derSignerInfos = new DERValue(DER.CONSTRUCTED | DER.SET,
463: b3.length, b3, null);
464:
465: ArrayList signedData = new ArrayList(6);
466: signedData.add(derVersion);
467: signedData.add(derDigestAlgorithms);
468: signedData.add(derContentInfo);
469: signedData.add(derExtendedCertificatesAndCertificates);
470: if (derCertificateRevocationLists != null)
471: signedData.add(derCertificateRevocationLists);
472:
473: signedData.add(derSignerInfos);
474: DERValue derSignedData = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
475: signedData);
476:
477: ArrayList outer = new ArrayList(3);
478: outer.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
479: outer.add(new DERValue(DER.CONTEXT | 0, null));
480: outer.add(derSignedData);
481: DERValue derOuter = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, outer);
482:
483: DERWriter.write(out, derOuter);
484: }
485: }