Source Code Cross Referenced for X509CertFactoryImpl.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » security » provider » cert » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » org package » org.apache.harmony.security.provider.cert 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         */
017:
018:        /**
019:         * @author Alexander Y. Kleymenov
020:         * @version $Revision$
021:         */package org.apache.harmony.security.provider.cert;
022:
023:        import java.io.IOException;
024:        import java.io.InputStream;
025:        import java.security.cert.CRL;
026:        import java.security.cert.CRLException;
027:        import java.security.cert.CertPath;
028:        import java.security.cert.Certificate;
029:        import java.security.cert.CertificateException;
030:        import java.security.cert.CertificateFactorySpi;
031:        import java.security.cert.X509CRL;
032:        import java.util.ArrayList;
033:        import java.util.Collection;
034:        import java.util.Iterator;
035:        import java.util.List;
036:
037:        import org.apache.harmony.luni.util.Base64;
038:        import org.apache.harmony.security.asn1.ASN1Constants;
039:        import org.apache.harmony.security.asn1.BerInputStream;
040:        import org.apache.harmony.security.internal.nls.Messages;
041:        import org.apache.harmony.security.pkcs7.ContentInfo;
042:        import org.apache.harmony.security.pkcs7.SignedData;
043:        import org.apache.harmony.security.x509.CertificateList;
044:
045:        /**
046:         * X509 Certificate Factory Service Provider Interface Implementation.
047:         * It supports CRLs and Certificates in (PEM) ASN.1 DER encoded form,
048:         * and Certification Paths in PkiPath and PKCS7 formats.
049:         * For Certificates and CRLs factory maintains the caching
050:         * mechanisms allowing to speed up repeated Certificate/CRL
051:         * generation.
052:         * @see Cache
053:         */
054:        public class X509CertFactoryImpl extends CertificateFactorySpi {
055:
056:            // number of leading/trailing bytes used for cert hash computation
057:            private static int CERT_CACHE_SEED_LENGTH = 28;
058:            // certificate cache
059:            private static Cache CERT_CACHE = new Cache(CERT_CACHE_SEED_LENGTH);
060:            // number of leading/trailing bytes used for crl hash computation
061:            private static int CRL_CACHE_SEED_LENGTH = 24;
062:            // crl cache
063:            private static Cache CRL_CACHE = new Cache(CRL_CACHE_SEED_LENGTH);
064:
065:            /**
066:             * Default constructor.
067:             * Creates the instance of Certificate Factory SPI ready for use.
068:             */
069:            public X509CertFactoryImpl() {
070:            }
071:
072:            /**
073:             * Generates the X.509 certificate from the data in the stream.
074:             * The data in the stream can be either in ASN.1 DER encoded X.509
075:             * certificate, or PEM (Base64 encoding bounded by
076:             * <code>"-----BEGIN CERTIFICATE-----"</code> at the beginning and
077:             * <code>"-----END CERTIFICATE-----"</code> at the end) representation
078:             * of the former encoded form.
079:             *
080:             * Before the generation the encoded form is looked up in
081:             * the cache. If the cache contains the certificate with requested encoded
082:             * form it is returned from it, otherwise it is generated by ASN.1
083:             * decoder.
084:             *
085:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCertificate(InputStream)
086:             * method documentation for more info
087:             */
088:            public Certificate engineGenerateCertificate(InputStream inStream)
089:                    throws CertificateException {
090:                if (inStream == null) {
091:                    throw new CertificateException(Messages
092:                            .getString("security.153")); //$NON-NLS-1$
093:                }
094:                try {
095:                    if (!inStream.markSupported()) {
096:                        // create the mark supporting wrapper
097:                        inStream = new RestoringInputStream(inStream);
098:                    }
099:                    // mark is needed to recognize the format of the provided encoding
100:                    // (ASN.1 or PEM)
101:                    inStream.mark(1);
102:                    // check whether the provided certificate is in PEM encoded form
103:                    if (inStream.read() == '-') {
104:                        // decode PEM, retrieve CRL
105:                        return getCertificate(decodePEM(inStream,
106:                                CERT_BOUND_SUFFIX));
107:                    } else {
108:                        inStream.reset();
109:                        // retrieve CRL
110:                        return getCertificate(inStream);
111:                    }
112:                } catch (IOException e) {
113:                    throw new CertificateException(e);
114:                }
115:            }
116:
117:            /**
118:             * Generates the collection of the certificates on the base of provided
119:             * via input stream encodings.
120:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCertificates(InputStream)
121:             * method documentation for more info
122:             */
123:            public Collection<? extends Certificate> engineGenerateCertificates(
124:                    InputStream inStream) throws CertificateException {
125:                if (inStream == null) {
126:                    throw new CertificateException(Messages
127:                            .getString("security.153")); //$NON-NLS-1$
128:                }
129:                ArrayList result = new ArrayList();
130:                try {
131:                    if (!inStream.markSupported()) {
132:                        // create the mark supporting wrapper
133:                        inStream = new RestoringInputStream(inStream);
134:                    }
135:                    // if it is PEM encoded form this array will contain the encoding
136:                    // so ((it is PEM) <-> (encoding != null))
137:                    byte[] encoding = null;
138:                    // The following by SEQUENCE ASN.1 tag, used for
139:                    // recognizing the data format 
140:                    // (is it PKCS7 ContentInfo structure, X.509 Certificate, or
141:                    // unsupported encoding)
142:                    int second_asn1_tag = -1;
143:                    inStream.mark(1);
144:                    int ch;
145:                    while ((ch = inStream.read()) != -1) {
146:                        // check if it is PEM encoded form
147:                        if (ch == '-') { // beginning of PEM encoding ('-' char)
148:                            // decode PEM chunk and store its content (ASN.1 encoding)
149:                            encoding = decodePEM(inStream, FREE_BOUND_SUFFIX);
150:                        } else if (ch == 0x30) { // beginning of ASN.1 sequence (0x30)
151:                            encoding = null;
152:                            inStream.reset();
153:                            // prepare for data format determination
154:                            inStream.mark(CERT_CACHE_SEED_LENGTH);
155:                        } else { // unsupported data
156:                            if (result.size() == 0) {
157:                                throw new CertificateException(Messages
158:                                        .getString("security.15F")); //$NON-NLS-1$
159:                            } else {
160:                                // it can be trailing user data,
161:                                // so keep it in the stream
162:                                inStream.reset();
163:                                return result;
164:                            }
165:                        }
166:                        // Check the data format
167:                        BerInputStream in = (encoding == null) ? new BerInputStream(
168:                                inStream)
169:                                : new BerInputStream(encoding);
170:                        // read the next ASN.1 tag
171:                        second_asn1_tag = in.next(); // inStream position changed
172:                        if (encoding == null) {
173:                            // keep whole structure in the stream
174:                            inStream.reset();
175:                        }
176:                        // check if it is a TBSCertificate structure
177:                        if (second_asn1_tag != ASN1Constants.TAG_C_SEQUENCE) {
178:                            if (result.size() == 0) {
179:                                // there were not read X.509 Certificates, so 
180:                                // break the cycle and check 
181:                                // whether it is PKCS7 structure
182:                                break;
183:                            } else {
184:                                // it can be trailing user data,
185:                                // so return what we already read
186:                                return result;
187:                            }
188:                        } else {
189:                            if (encoding == null) {
190:                                result.add(getCertificate(inStream));
191:                            } else {
192:                                result.add(getCertificate(encoding));
193:                            }
194:                        }
195:                        // mark for the next iteration
196:                        inStream.mark(1);
197:                    }
198:                    if (result.size() != 0) {
199:                        // some Certificates have been read
200:                        return result;
201:                    } else if (ch == -1) {
202:                        throw new CertificateException(Messages
203:                                .getString("security.155")); //$NON-NLS-1$
204:                    }
205:                    // else: check if it is PKCS7
206:                    if (second_asn1_tag == ASN1Constants.TAG_OID) {
207:                        // it is PKCS7 ContentInfo structure, so decode it
208:                        ContentInfo info = (ContentInfo) ((encoding != null) ? ContentInfo.ASN1
209:                                .decode(encoding)
210:                                : ContentInfo.ASN1.decode(inStream));
211:                        // retrieve SignedData
212:                        SignedData data = info.getSignedData();
213:                        if (data == null) {
214:                            throw new CertificateException(Messages
215:                                    .getString("security.154")); //$NON-NLS-1$
216:                        }
217:                        List certs = data.getCertificates();
218:                        if (certs != null) {
219:                            for (int i = 0; i < certs.size(); i++) {
220:                                result
221:                                        .add(new X509CertImpl(
222:                                                (org.apache.harmony.security.x509.Certificate) certs
223:                                                        .get(i)));
224:                            }
225:                        }
226:                        return result;
227:                    }
228:                    // else: Unknown data format
229:                    throw new CertificateException(Messages
230:                            .getString("security.15F")); //$NON-NLS-1$
231:                } catch (IOException e) {
232:                    throw new CertificateException(e);
233:                }
234:            }
235:
236:            /**
237:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCRL(InputStream)
238:             * method documentation for more info
239:             */
240:            public CRL engineGenerateCRL(InputStream inStream)
241:                    throws CRLException {
242:                if (inStream == null) {
243:                    throw new CRLException(Messages.getString("security.153")); //$NON-NLS-1$
244:                }
245:                try {
246:                    if (!inStream.markSupported()) {
247:                        // Create the mark supporting wrapper
248:                        // Mark is needed to recognize the format 
249:                        // of provided encoding form (ASN.1 or PEM)
250:                        inStream = new RestoringInputStream(inStream);
251:                    }
252:                    inStream.mark(1);
253:                    // check whether the provided crl is in PEM encoded form
254:                    if (inStream.read() == '-') {
255:                        // decode PEM, retrieve CRL
256:                        return getCRL(decodePEM(inStream, FREE_BOUND_SUFFIX));
257:                    } else {
258:                        inStream.reset();
259:                        // retrieve CRL
260:                        return getCRL(inStream);
261:                    }
262:                } catch (IOException e) {
263:                    throw new CRLException(e);
264:                }
265:            }
266:
267:            /**
268:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCRLs(InputStream)
269:             * method documentation for more info
270:             */
271:            public Collection<? extends CRL> engineGenerateCRLs(
272:                    InputStream inStream) throws CRLException {
273:                if (inStream == null) {
274:                    throw new CRLException(Messages.getString("security.153")); //$NON-NLS-1$
275:                }
276:                ArrayList result = new ArrayList();
277:                try {
278:                    if (!inStream.markSupported()) {
279:                        inStream = new RestoringInputStream(inStream);
280:                    }
281:                    // if it is PEM encoded form this array will contain the encoding
282:                    // so ((it is PEM) <-> (encoding != null))
283:                    byte[] encoding = null;
284:                    // The following by SEQUENCE ASN.1 tag, used for
285:                    // recognizing the data format 
286:                    // (is it PKCS7 ContentInfo structure, X.509 CRL, or
287:                    // unsupported encoding)
288:                    int second_asn1_tag = -1;
289:                    inStream.mark(1);
290:                    int ch;
291:                    while ((ch = inStream.read()) != -1) {
292:                        // check if it is PEM encoded form
293:                        if (ch == '-') { // beginning of PEM encoding ('-' char)
294:                            // decode PEM chunk and store its content (ASN.1 encoding)
295:                            encoding = decodePEM(inStream, FREE_BOUND_SUFFIX);
296:                        } else if (ch == 0x30) { // beginning of ASN.1 sequence (0x30)
297:                            encoding = null;
298:                            inStream.reset();
299:                            // prepare for data format determination
300:                            inStream.mark(CRL_CACHE_SEED_LENGTH);
301:                        } else { // unsupported data
302:                            if (result.size() == 0) {
303:                                throw new CRLException(Messages
304:                                        .getString("security.15F")); //$NON-NLS-1$
305:                            } else {
306:                                // it can be trailing user data,
307:                                // so keep it in the stream
308:                                inStream.reset();
309:                                return result;
310:                            }
311:                        }
312:                        // Check the data format
313:                        BerInputStream in = (encoding == null) ? new BerInputStream(
314:                                inStream)
315:                                : new BerInputStream(encoding);
316:                        // read the next ASN.1 tag
317:                        second_asn1_tag = in.next();
318:                        if (encoding == null) {
319:                            // keep whole structure in the stream
320:                            inStream.reset();
321:                        }
322:                        // check if it is a TBSCertList structure
323:                        if (second_asn1_tag != ASN1Constants.TAG_C_SEQUENCE) {
324:                            if (result.size() == 0) {
325:                                // there were not read X.509 CRLs, so 
326:                                // break the cycle and check 
327:                                // whether it is PKCS7 structure
328:                                break;
329:                            } else {
330:                                // it can be trailing user data,
331:                                // so return what we already read
332:                                return result;
333:                            }
334:                        } else {
335:                            if (encoding == null) {
336:                                result.add(getCRL(inStream));
337:                            } else {
338:                                result.add(getCRL(encoding));
339:                            }
340:                        }
341:                        inStream.mark(1);
342:                    }
343:                    if (result.size() != 0) {
344:                        // the stream was read out
345:                        return result;
346:                    } else if (ch == -1) {
347:                        throw new CRLException(Messages
348:                                .getString("security.155")); //$NON-NLS-1$
349:                    }
350:                    // else: check if it is PKCS7
351:                    if (second_asn1_tag == ASN1Constants.TAG_OID) {
352:                        // it is PKCS7 ContentInfo structure, so decode it
353:                        ContentInfo info = (ContentInfo) ((encoding != null) ? ContentInfo.ASN1
354:                                .decode(encoding)
355:                                : ContentInfo.ASN1.decode(inStream));
356:                        // retrieve SignedData
357:                        SignedData data = info.getSignedData();
358:                        if (data == null) {
359:                            throw new CRLException(Messages
360:                                    .getString("security.154")); //$NON-NLS-1$
361:                        }
362:                        List crls = data.getCRLs();
363:                        if (crls != null) {
364:                            for (int i = 0; i < crls.size(); i++) {
365:                                result.add(new X509CRLImpl(
366:                                        (CertificateList) crls.get(i)));
367:                            }
368:                        }
369:                        return result;
370:                    }
371:                    // else: Unknown data format
372:                    throw new CRLException(Messages.getString("security.15F")); //$NON-NLS-1$
373:                } catch (IOException e) {
374:                    throw new CRLException(e);
375:                }
376:            }
377:
378:            /**
379:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCertPath(InputStream)
380:             * method documentation for more info
381:             */
382:            public CertPath engineGenerateCertPath(InputStream inStream)
383:                    throws CertificateException {
384:                if (inStream == null) {
385:                    throw new CertificateException(Messages
386:                            .getString("security.153")); //$NON-NLS-1$
387:                }
388:                return engineGenerateCertPath(inStream, "PkiPath"); //$NON-NLS-1$
389:            }
390:
391:            /**
392:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCertPath(InputStream,String)
393:             * method documentation for more info
394:             */
395:            public CertPath engineGenerateCertPath(InputStream inStream,
396:                    String encoding) throws CertificateException {
397:                if (inStream == null) {
398:                    throw new CertificateException(Messages
399:                            .getString("security.153")); //$NON-NLS-1$
400:                }
401:                if (!inStream.markSupported()) {
402:                    inStream = new RestoringInputStream(inStream);
403:                }
404:                try {
405:                    inStream.mark(1);
406:                    int ch;
407:
408:                    // check if it is PEM encoded form
409:                    if ((ch = inStream.read()) == '-') {
410:                        // decode PEM chunk into ASN.1 form and decode CertPath object
411:                        return X509CertPathImpl.getInstance(decodePEM(inStream,
412:                                FREE_BOUND_SUFFIX), encoding);
413:                    } else if (ch == 0x30) { // ASN.1 Sequence
414:                        inStream.reset();
415:                        // decode ASN.1 form
416:                        return X509CertPathImpl.getInstance(inStream, encoding);
417:                    } else {
418:                        throw new CertificateException(Messages
419:                                .getString("security.15F")); //$NON-NLS-1$
420:                    }
421:                } catch (IOException e) {
422:                    throw new CertificateException(e);
423:                }
424:            }
425:
426:            /**
427:             * @see java.security.cert.CertificateFactorySpi#engineGenerateCertPath(List)
428:             * method documentation for more info
429:             */
430:            public CertPath engineGenerateCertPath(List certificates)
431:                    throws CertificateException {
432:                return new X509CertPathImpl(certificates);
433:            }
434:
435:            /**
436:             * @see java.security.cert.CertificateFactorySpi#engineGetCertPathEncodings()
437:             * method documentation for more info
438:             */
439:            public Iterator<String> engineGetCertPathEncodings() {
440:                return X509CertPathImpl.encodings.iterator();
441:            }
442:
443:            // ---------------------------------------------------------------------
444:            // ------------------------ Staff methods ------------------------------
445:            // ---------------------------------------------------------------------
446:
447:            private static byte[] pemBegin = "-----BEGIN".getBytes(); //$NON-NLS-1$
448:            private static byte[] pemClose = "-----END".getBytes(); //$NON-NLS-1$
449:            /**
450:             * Code describing free format for PEM boundary suffix:
451:             * "^-----BEGIN.*\n"         at the beginning, and<br>
452:             * "\n-----END.*(EOF|\n)$"   at the end.
453:             */
454:            private static byte[] FREE_BOUND_SUFFIX = null;
455:            /**
456:             * Code describing PEM boundary suffix for X.509 certificate:
457:             * "^-----BEGIN CERTIFICATE-----\n"   at the beginning, and<br>
458:             * "\n-----END CERTIFICATE-----"   at the end.
459:             */
460:            private static byte[] CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes(); //$NON-NLS-1$
461:
462:            /**
463:             * Method retrieves the PEM encoded data from the stream 
464:             * and returns its decoded representation.
465:             * Method checks correctness of PEM boundaries. It supposes that
466:             * the first '-' of the opening boundary has already been read from
467:             * the stream. So first of all it checks that the leading bytes
468:             * are equal to "-----BEGIN" boundary prefix. Than if boundary_suffix
469:             * is not null, it checks that next bytes equal to boundary_suffix
470:             * + new line char[s] ([CR]LF).
471:             * If boundary_suffix parameter is null, method supposes free suffix
472:             * format and skips any bytes until the new line.<br>
473:             * After the opening boundary has been read and checked, the method
474:             * read Base64 encoded data until closing PEM boundary is not reached.<br>
475:             * Than it checks closing boundary - it should start with new line +
476:             * "-----END" + boundary_suffix. If boundary_suffix is null, 
477:             * any characters are skipped until the new line.<br>
478:             * After this any trailing new line characters are skipped from the stream,
479:             * Base64 encoding is decoded and returned.
480:             * @param inStream the stream containing the PEM encoding.
481:             * @param boundary_suffix the suffix of expected PEM multipart 
482:             * boundary delimiter.<br>
483:             * If it is null, that any character sequences are accepted.
484:             * @throws IOException If PEM boundary delimiter does not comply 
485:             * with expected or some I/O or decoding problems occur.
486:             */
487:            private byte[] decodePEM(InputStream inStream,
488:                    byte[] boundary_suffix) throws IOException {
489:                int ch; // the char to be read
490:                // check and skip opening boundary delimiter 
491:                // (first '-' is supposed as already read)
492:                for (int i = 1; i < pemBegin.length; i++) {
493:                    if (pemBegin[i] != (ch = inStream.read())) {
494:                        throw new IOException(
495:                                "Incorrect PEM encoding: '-----BEGIN"
496:                                        + ((boundary_suffix == null) ? ""
497:                                                : new String(boundary_suffix))
498:                                        + "' is expected as opening delimiter boundary.");
499:                    }
500:                }
501:                if (boundary_suffix == null) {
502:                    // read (skip) the trailing characters of 
503:                    // the beginning PEM boundary delimiter
504:                    while ((ch = inStream.read()) != '\n') {
505:                        if (ch == -1) {
506:                            throw new IOException(Messages
507:                                    .getString("security.156")); //$NON-NLS-1$
508:                        }
509:                    }
510:                } else {
511:                    for (int i = 0; i < boundary_suffix.length; i++) {
512:                        if (boundary_suffix[i] != inStream.read()) {
513:                            throw new IOException(Messages.getString(
514:                                    "security.15B", //$NON-NLS-1$
515:                                    new String(boundary_suffix))); //$NON-NLS-1$
516:                        }
517:                    }
518:                    // read new line characters
519:                    if ((ch = inStream.read()) == '\r') {
520:                        // CR has been read, now read LF character
521:                        ch = inStream.read();
522:                    }
523:                    if (ch != '\n') {
524:                        throw new IOException(Messages
525:                                .getString("security.15B2")); //$NON-NLS-1$
526:                    }
527:                }
528:                int size = 1024; // the size of the buffer containing Base64 data
529:                byte[] buff = new byte[size];
530:                int index = 0;
531:                // read bytes while ending boundary delimiter is not reached
532:                while ((ch = inStream.read()) != '-') {
533:                    if (ch == -1) {
534:                        throw new IOException(Messages
535:                                .getString("security.157")); //$NON-NLS-1$
536:                    }
537:                    buff[index++] = (byte) ch;
538:                    if (index == size) {
539:                        // enlarge the buffer
540:                        byte[] newbuff = new byte[size + 1024];
541:                        System.arraycopy(buff, 0, newbuff, 0, size);
542:                        buff = newbuff;
543:                        size += 1024;
544:                    }
545:                }
546:                if (buff[index - 1] != '\n') {
547:                    throw new IOException(Messages.getString("security.158")); //$NON-NLS-1$
548:                }
549:                // check and skip closing boundary delimiter prefix
550:                // (first '-' was read)
551:                for (int i = 1; i < pemClose.length; i++) {
552:                    if (pemClose[i] != inStream.read()) {
553:                        throw new IOException(Messages.getString(
554:                                "security.15B1", //$NON-NLS-1$
555:                                ((boundary_suffix == null) ? "" : new String(
556:                                        boundary_suffix)))); //$NON-NLS-1$
557:                    }
558:                }
559:                if (boundary_suffix == null) {
560:                    // read (skip) the trailing characters of 
561:                    // the closing PEM boundary delimiter
562:                    while (((ch = inStream.read()) != -1) && (ch != '\n')
563:                            && (ch != '\r')) {
564:                    }
565:                } else {
566:                    for (int i = 0; i < boundary_suffix.length; i++) {
567:                        if (boundary_suffix[i] != inStream.read()) {
568:                            throw new IOException(Messages.getString(
569:                                    "security.15B1", //$NON-NLS-1$
570:                                    new String(boundary_suffix))); //$NON-NLS-1$
571:                        }
572:                    }
573:                }
574:                // skip trailing line breaks
575:                inStream.mark(1);
576:                while (((ch = inStream.read()) != -1)
577:                        && (ch == '\n' || ch == '\r')) {
578:                    inStream.mark(1);
579:                }
580:                inStream.reset();
581:                buff = Base64.decode(buff, index);
582:                if (buff == null) {
583:                    throw new IOException(Messages.getString("security.159")); //$NON-NLS-1$
584:                }
585:                return buff;
586:            };
587:
588:            /**
589:             * Reads the data of specified length from source 
590:             * and returns it as an array.
591:             * @return the byte array contained read data or 
592:             * null if the stream contains not enough data
593:             * @throws IOException if some I/O error has been occurred.
594:             */
595:            private static byte[] readBytes(InputStream source, int length)
596:                    throws IOException {
597:                byte[] result = new byte[length];
598:                for (int i = 0; i < length; i++) {
599:                    int bytik = source.read();
600:                    if (bytik == -1) {
601:                        return null;
602:                    }
603:                    result[i] = (byte) bytik;
604:                }
605:                return result;
606:            }
607:
608:            /**
609:             * Returns the Certificate object corresponding to the provided encoding.
610:             * Resulting object is retrieved from the cache 
611:             * if it contains such correspondence 
612:             * and is constructed on the base of encoding 
613:             * and stored in the cache otherwise.
614:             * @throws IOException if some decoding errors occur
615:             * (in the case of cache miss).
616:             */
617:            private static Certificate getCertificate(byte[] encoding)
618:                    throws CertificateException, IOException {
619:                if (encoding.length < CERT_CACHE_SEED_LENGTH) {
620:                    throw new CertificateException(Messages
621:                            .getString("security.152")); //$NON-NLS-1$
622:                }
623:                synchronized (CERT_CACHE) {
624:                    long hash = CERT_CACHE.getHash(encoding);
625:                    if (CERT_CACHE.contains(hash)) {
626:                        Certificate res = (Certificate) CERT_CACHE.get(hash,
627:                                encoding);
628:                        if (res != null) {
629:                            return res;
630:                        }
631:                    }
632:                    Certificate res = new X509CertImpl(encoding);
633:                    CERT_CACHE.put(hash, encoding, res);
634:                    return res;
635:                }
636:            }
637:
638:            /**
639:             * Returns the Certificate object corresponding to the encoding provided
640:             * by the stream.
641:             * Resulting object is retrieved from the cache 
642:             * if it contains such correspondence 
643:             * and is constructed on the base of encoding 
644:             * and stored in the cache otherwise.
645:             * @throws IOException if some decoding errors occur
646:             * (in the case of cache miss).
647:             */
648:            private static Certificate getCertificate(InputStream inStream)
649:                    throws CertificateException, IOException {
650:                synchronized (CERT_CACHE) {
651:                    inStream.mark(CERT_CACHE_SEED_LENGTH);
652:                    // read the prefix of the encoding
653:                    byte[] buff = readBytes(inStream, CERT_CACHE_SEED_LENGTH);
654:                    inStream.reset();
655:                    if (buff == null) {
656:                        throw new CertificateException(Messages
657:                                .getString("security.152")); //$NON-NLS-1$
658:                    }
659:                    long hash = CERT_CACHE.getHash(buff);
660:                    if (CERT_CACHE.contains(hash)) {
661:                        byte[] encoding = new byte[BerInputStream
662:                                .getLength(buff)];
663:                        if (encoding.length < CERT_CACHE_SEED_LENGTH) {
664:                            throw new CertificateException(Messages
665:                                    .getString("security.15B3")); //$NON-NLS-1$
666:                        }
667:                        inStream.read(encoding);
668:                        Certificate res = (Certificate) CERT_CACHE.get(hash,
669:                                encoding);
670:                        if (res != null) {
671:                            return res;
672:                        }
673:                        res = new X509CertImpl(encoding);
674:                        CERT_CACHE.put(hash, encoding, res);
675:                        return res;
676:                    } else {
677:                        inStream.reset();
678:                        Certificate res = new X509CertImpl(inStream);
679:                        CERT_CACHE.put(hash, res.getEncoded(), res);
680:                        return res;
681:                    }
682:                }
683:            }
684:
685:            /**
686:             * Returns the CRL object corresponding to the provided encoding.
687:             * Resulting object is retrieved from the cache 
688:             * if it contains such correspondence 
689:             * and is constructed on the base of encoding 
690:             * and stored in the cache otherwise.
691:             * @throws IOException if some decoding errors occur
692:             * (in the case of cache miss).
693:             */
694:            private static CRL getCRL(byte[] encoding) throws CRLException,
695:                    IOException {
696:                if (encoding.length < CRL_CACHE_SEED_LENGTH) {
697:                    throw new CRLException(Messages.getString("security.152")); //$NON-NLS-1$
698:                }
699:                synchronized (CRL_CACHE) {
700:                    long hash = CRL_CACHE.getHash(encoding);
701:                    if (CRL_CACHE.contains(hash)) {
702:                        X509CRL res = (X509CRL) CRL_CACHE.get(hash, encoding);
703:                        if (res != null) {
704:                            return res;
705:                        }
706:                    }
707:                    X509CRL res = new X509CRLImpl(encoding);
708:                    CRL_CACHE.put(hash, encoding, res);
709:                    return res;
710:                }
711:            }
712:
713:            /**
714:             * Returns the CRL object corresponding to the encoding provided
715:             * by the stream.
716:             * Resulting object is retrieved from the cache 
717:             * if it contains such correspondence 
718:             * and is constructed on the base of encoding 
719:             * and stored in the cache otherwise.
720:             * @throws IOException if some decoding errors occur
721:             * (in the case of cache miss).
722:             */
723:            private static CRL getCRL(InputStream inStream)
724:                    throws CRLException, IOException {
725:                synchronized (CRL_CACHE) {
726:                    inStream.mark(CRL_CACHE_SEED_LENGTH);
727:                    byte[] buff = readBytes(inStream, CRL_CACHE_SEED_LENGTH);
728:                    // read the prefix of the encoding
729:                    inStream.reset();
730:                    if (buff == null) {
731:                        throw new CRLException(Messages
732:                                .getString("security.152")); //$NON-NLS-1$
733:                    }
734:                    long hash = CRL_CACHE.getHash(buff);
735:                    if (CRL_CACHE.contains(hash)) {
736:                        byte[] encoding = new byte[BerInputStream
737:                                .getLength(buff)];
738:                        if (encoding.length < CRL_CACHE_SEED_LENGTH) {
739:                            throw new CRLException(Messages
740:                                    .getString("security.15B4")); //$NON-NLS-1$
741:                        }
742:                        inStream.read(encoding);
743:                        CRL res = (CRL) CRL_CACHE.get(hash, encoding);
744:                        if (res != null) {
745:                            return res;
746:                        }
747:                        res = new X509CRLImpl(encoding);
748:                        CRL_CACHE.put(hash, encoding, res);
749:                        return res;
750:                    } else {
751:                        X509CRL res = new X509CRLImpl(inStream);
752:                        CRL_CACHE.put(hash, res.getEncoded(), res);
753:                        return res;
754:                    }
755:                }
756:            }
757:
758:            /*
759:             * This class extends any existing input stream with
760:             * mark functionality. It acts as a wrapper over the
761:             * stream and supports reset to the
762:             * marked state with readlimit no more than BUFF_SIZE.
763:             */
764:            private static class RestoringInputStream extends InputStream {
765:
766:                // wrapped input stream
767:                private final InputStream inStream;
768:                // specifies how much of the read data is buffered
769:                // after the mark has been set up
770:                private static final int BUFF_SIZE = 32;
771:                // buffer to keep the bytes read after the mark has been set up
772:                private final int[] buff = new int[BUFF_SIZE * 2];
773:                // position of the next byte to read,
774:                // the value of -1 indicates that the buffer is not used
775:                // (mark was not set up or was invalidated, or reset to the marked
776:                // position has been done and all the buffered data was read out)
777:                private int pos = -1;
778:                // position of the last buffered byte
779:                private int bar = 0;
780:                // position in the buffer where the mark becomes invalidated
781:                private int end = 0;
782:
783:                /**
784:                 * Creates the mark supporting wrapper over the stream.
785:                 */
786:                public RestoringInputStream(InputStream inStream) {
787:                    this .inStream = inStream;
788:                }
789:
790:                /**
791:                 * @see java.io.InputStream#available()
792:                 * method documentation for more info
793:                 */
794:                public int available() throws IOException {
795:                    return (bar - pos) + inStream.available();
796:                }
797:
798:                /**
799:                 * @see java.io.InputStream#close()
800:                 * method documentation for more info
801:                 */
802:                public void close() throws IOException {
803:                    inStream.close();
804:                }
805:
806:                /**
807:                 * @see java.io.InputStream#mark(int readlimit)
808:                 * method documentation for more info
809:                 */
810:                public void mark(int readlimit) {
811:                    if (pos < 0) {
812:                        pos = 0;
813:                        bar = 0;
814:                        end = BUFF_SIZE - 1;
815:                    } else {
816:                        end = (pos + BUFF_SIZE - 1) % BUFF_SIZE;
817:                    }
818:                }
819:
820:                /**
821:                 * @see java.io.InputStream#markSupported()
822:                 * method documentation for more info
823:                 */
824:                public boolean markSupported() {
825:                    return true;
826:                }
827:
828:                /**
829:                 * Reads the byte from the stream. If mark has been set up
830:                 * and was not invalidated byte is read from the underlying
831:                 * stream and saved into the buffer. If the current read position
832:                 * has been reset to the marked position and there are remaining
833:                 * bytes in the buffer, the byte is taken from it. In the other cases
834:                 * (if mark has been invalidated, or there are no buffered bytes)
835:                 * the byte is taken directly from the underlying stream and it is
836:                 * returned without saving to the buffer.
837:                 *
838:                 * @see java.io.InputStream#read()
839:                 * method documentation for more info
840:                 */
841:                public int read() throws IOException {
842:                    // if buffer is currently used
843:                    if (pos >= 0) {
844:                        // current position in the buffer
845:                        int cur = pos % BUFF_SIZE;
846:                        // check whether the buffer contains the data to be read
847:                        if (cur < bar) {
848:                            // return the data from the buffer
849:                            pos++;
850:                            return buff[cur];
851:                        }
852:                        // check whether buffer has free space
853:                        if (cur != end) {
854:                            // it has, so read the data from the wrapped stream
855:                            // and place it in the buffer
856:                            buff[cur] = inStream.read();
857:                            bar = cur + 1;
858:                            pos++;
859:                            return buff[cur];
860:                        } else {
861:                            // buffer if full and can not operate
862:                            // any more, so invalidate the mark position
863:                            // and turn off the using of buffer
864:                            pos = -1;
865:                        }
866:                    }
867:                    // buffer is not used, so return the data from the wrapped stream
868:                    return inStream.read();
869:                }
870:
871:                /**
872:                 * @see java.io.InputStream#read(byte[] b)
873:                 * method documentation for more info
874:                 */
875:                public int read(byte[] b) throws IOException {
876:                    return read(b, 0, b.length);
877:                }
878:
879:                /**
880:                 * @see java.io.InputStream#read(byte[] b, int off, int len)
881:                 * method documentation for more info
882:                 */
883:                public int read(byte[] b, int off, int len) throws IOException {
884:                    int read_b;
885:                    int i;
886:                    for (i = 0; i < len; i++) {
887:                        if ((read_b = read()) == -1) {
888:                            return (i == 0) ? -1 : i;
889:                        }
890:                        b[off + i] = (byte) read_b;
891:                    }
892:                    return i;
893:                }
894:
895:                /**
896:                 * @see java.io.InputStream#reset()
897:                 * method documentation for more info
898:                 */
899:                public void reset() throws IOException {
900:                    if (pos >= 0) {
901:                        pos = (end + 1) % BUFF_SIZE;
902:                    } else {
903:                        throw new IOException(Messages
904:                                .getString("security.15A")); //$NON-NLS-1$
905:                    }
906:                }
907:
908:                /**
909:                 * @see java.io.InputStream#skip(long n)
910:                 * method documentation for more info
911:                 */
912:                public long skip(long n) throws IOException {
913:                    if (pos >= 0) {
914:                        long i = 0;
915:                        int av = available();
916:                        if (av < n) {
917:                            n = av;
918:                        }
919:                        while ((i < n) && (read() != -1)) {
920:                            i++;
921:                        }
922:                        return i;
923:                    } else {
924:                        return inStream.skip(n);
925:                    }
926:                }
927:            }
928:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.