1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46:
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62:
63:
68: public class X509CertPath extends CertPath
69: {
70:
71:
72:
73:
74: public static final List ENCODINGS = Collections.unmodifiableList(
75: Arrays.asList(new String[] { "PkiPath", "PKCS7" }));
76:
77: private static final OID PKCS7_SIGNED_DATA = new OID("1.2.840.113549.1.7.2");
78: private static final OID PKCS7_DATA = new OID("1.2.840.113549.1.7.1");
79:
80:
81: private List path;
82:
83:
84: private byte[] pkcs_encoded;
85:
86:
87: private byte[] pki_encoded;
88:
89:
90:
91:
92: public X509CertPath(List path)
93: {
94: super("X.509");
95: this.path = Collections.unmodifiableList(path);
96: }
97:
98: public X509CertPath(InputStream in) throws CertificateEncodingException
99: {
100: this(in, (String) ENCODINGS.get(0));
101: }
102:
103: public X509CertPath(InputStream in, String encoding)
104: throws CertificateEncodingException
105: {
106: super("X.509");
107: try
108: {
109: parse(in, encoding);
110: }
111: catch (IOException ioe)
112: {
113: throw new CertificateEncodingException();
114: }
115: }
116:
117:
118:
119:
120: public List getCertificates()
121: {
122: return path;
123: }
124:
125: public byte[] getEncoded() throws CertificateEncodingException
126: {
127: return getEncoded((String) ENCODINGS.get(0));
128: }
129:
130: public byte[] getEncoded(String encoding) throws CertificateEncodingException
131: {
132: if (encoding.equalsIgnoreCase("PkiPath"))
133: {
134: if (pki_encoded == null)
135: {
136: try
137: {
138: pki_encoded = encodePki();
139: }
140: catch (IOException ioe)
141: {
142: throw new CertificateEncodingException();
143: }
144: }
145: return (byte[]) pki_encoded.clone();
146: }
147: else if (encoding.equalsIgnoreCase("PKCS7"))
148: {
149: if (pkcs_encoded == null)
150: {
151: try
152: {
153: pkcs_encoded = encodePKCS();
154: }
155: catch (IOException ioe)
156: {
157: throw new CertificateEncodingException();
158: }
159: }
160: return (byte[]) pkcs_encoded.clone();
161: }
162: else
163: throw new CertificateEncodingException("unknown encoding: " + encoding);
164: }
165:
166: public Iterator getEncodings()
167: {
168: return ENCODINGS.iterator();
169: }
170:
171:
172:
173:
174: private void parse(InputStream in, String encoding)
175: throws CertificateEncodingException, IOException
176: {
177: DERReader der = new DERReader(in);
178: DERValue path = null;
179: if (encoding.equalsIgnoreCase("PkiPath"))
180: {
181:
182: path = der.read();
183: if (!path.isConstructed())
184: throw new DEREncodingException("malformed PkiPath");
185: }
186: else if (encoding.equalsIgnoreCase("PKCS7"))
187: {
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208: DERValue value = der.read();
209: if (!value.isConstructed())
210: throw new DEREncodingException("malformed ContentInfo");
211: value = der.read();
212: if (!(value.getValue() instanceof OID) ||
213: ((OID) value.getValue()).equals(PKCS7_SIGNED_DATA))
214: throw new DEREncodingException("not a SignedData");
215: value = der.read();
216: if (!value.isConstructed() || value.getTag() != 0)
217: throw new DEREncodingException("malformed content");
218: value = der.read();
219: if (value.getTag() != DER.INTEGER)
220: throw new DEREncodingException("malformed Version");
221: value = der.read();
222: if (!value.isConstructed() || value.getTag() != DER.SET)
223: throw new DEREncodingException("malformed DigestAlgorithmIdentifiers");
224: der.skip(value.getLength());
225: value = der.read();
226: if (!value.isConstructed())
227: throw new DEREncodingException("malformed ContentInfo");
228: der.skip(value.getLength());
229: path = der.read();
230: if (!path.isConstructed() || path.getTag() != 0)
231: throw new DEREncodingException("no certificates");
232: }
233: else
234: throw new CertificateEncodingException("unknown encoding: " + encoding);
235:
236: LinkedList certs = new LinkedList();
237: int len = 0;
238: while (len < path.getLength())
239: {
240: DERValue cert = der.read();
241: try
242: {
243: certs.add(new X509Certificate(new ByteArrayInputStream(cert.getEncoded())));
244: }
245: catch (CertificateException ce)
246: {
247: throw new CertificateEncodingException(ce.getMessage());
248: }
249: len += cert.getEncodedLength();
250: der.skip(cert.getLength());
251: }
252:
253: this.path = Collections.unmodifiableList(certs);
254: }
255:
256: private byte[] encodePki()
257: throws CertificateEncodingException, IOException
258: {
259: synchronized (path)
260: {
261: ByteArrayOutputStream out = new ByteArrayOutputStream();
262: for (Iterator i = path.iterator(); i.hasNext(); )
263: {
264: out.write(((Certificate) i.next()).getEncoded());
265: }
266: byte[] b = out.toByteArray();
267: DERValue val = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
268: b.length, b, null);
269: return val.getEncoded();
270: }
271: }
272:
273: private byte[] encodePKCS()
274: throws CertificateEncodingException, IOException
275: {
276: synchronized (path)
277: {
278: ArrayList signedData = new ArrayList(5);
279: signedData.add(new DERValue(DER.INTEGER, BigInteger.ONE));
280: signedData.add(new DERValue(DER.CONSTRUCTED | DER.SET,
281: Collections.EMPTY_SET));
282: signedData.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
283: Collections.singletonList(
284: new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_DATA))));
285: ByteArrayOutputStream out = new ByteArrayOutputStream();
286: for (Iterator i = path.iterator(); i.hasNext(); )
287: {
288: out.write(((Certificate) i.next()).getEncoded());
289: }
290: byte[] b = out.toByteArray();
291: signedData.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT,
292: b.length, b, null));
293: DERValue sdValue = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
294: signedData);
295:
296: ArrayList contentInfo = new ArrayList(2);
297: contentInfo.add(new DERValue(DER.OBJECT_IDENTIFIER, PKCS7_SIGNED_DATA));
298: contentInfo.add(new DERValue(DER.CONSTRUCTED | DER.CONTEXT, sdValue));
299: return new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
300: contentInfo).getEncoded();
301: }
302: }
303: }