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