Source Code Cross Referenced for X509CertImpl.java in  » 6.0-JDK-Modules » j2me » sun » security » x509 » 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 » 6.0 JDK Modules » j2me » sun.security.x509 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)X509CertImpl.java	1.5 06/10/10
0003:         *
0004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
0006:         *   
0007:         * This program is free software; you can redistribute it and/or  
0008:         * modify it under the terms of the GNU General Public License version  
0009:         * 2 only, as published by the Free Software Foundation.   
0010:         *   
0011:         * This program is distributed in the hope that it will be useful, but  
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
0014:         * General Public License version 2 for more details (a copy is  
0015:         * included at /legal/license.txt).   
0016:         *   
0017:         * You should have received a copy of the GNU General Public License  
0018:         * version 2 along with this work; if not, write to the Free Software  
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
0020:         * 02110-1301 USA   
0021:         *   
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
0024:         * information or have any questions. 
0025:         *
0026:         */
0027:
0028:        /*
0029:         * Note that there are two versions of X509CertImpl, this
0030:         * subsetted one for CDC/FP and another for the security optional
0031:         * package. Be sure you're editing the right one!
0032:         */
0033:
0034:        package sun.security.x509;
0035:
0036:        import java.io.BufferedReader;
0037:        import java.io.BufferedInputStream;
0038:        import java.io.ByteArrayOutputStream;
0039:        import java.io.IOException;
0040:        import java.io.InputStream;
0041:        import java.io.InputStreamReader;
0042:        import java.io.OutputStream;
0043:        import java.math.BigInteger;
0044:        import java.security.*;
0045:        import java.security.cert.*;
0046:        import java.security.cert.Certificate;
0047:        import java.util.*;
0048:
0049:        import javax.security.auth.x500.X500Principal;
0050:
0051:        import sun.misc.HexDumpEncoder;
0052:        import sun.misc.BASE64Decoder;
0053:        import sun.security.util.*;
0054:        import sun.security.provider.X509Factory;
0055:
0056:        /**
0057:         * The X509CertImpl class represents an X.509 certificate. These certificates
0058:         * are widely used to support authentication and other functionality in
0059:         * Internet security systems.  Common applications include Privacy Enhanced
0060:         * Mail (PEM), Transport Layer Security (SSL), code signing for trusted
0061:         * software distribution, and Secure Electronic Transactions (SET).  There
0062:         * is a commercial infrastructure ready to manage large scale deployments
0063:         * of X.509 identity certificates.
0064:         *
0065:         * <P>These certificates are managed and vouched for by <em>Certificate
0066:         * Authorities</em> (CAs).  CAs are services which create certificates by
0067:         * placing data in the X.509 standard format and then digitally signing
0068:         * that data.  Such signatures are quite difficult to forge.  CAs act as
0069:         * trusted third parties, making introductions between agents who have no
0070:         * direct knowledge of each other.  CA certificates are either signed by
0071:         * themselves, or by some other CA such as a "root" CA.
0072:         *
0073:         * <P>RFC 1422 is very informative, though it does not describe much
0074:         * of the recent work being done with X.509 certificates.  That includes
0075:         * a 1996 version (X.509v3) and a variety of enhancements being made to
0076:         * facilitate an explosion of personal certificates used as "Internet
0077:         * Drivers' Licences", or with SET for credit card transactions.
0078:         *
0079:         * <P>More recent work includes the IETF PKIX Working Group efforts,
0080:         * especially RFC2459.
0081:         *
0082:         * @author Dave Brownell
0083:         * @author Amit Kapoor
0084:         * @author Hemma Prafullchandra
0085:         * @version 1.109 02/02/00
0086:         * @see X509CertInfo
0087:         */
0088:        public class X509CertImpl extends X509Certificate implements  DerEncoder {
0089:
0090:            private static final String DOT = ".";
0091:            /**
0092:             * Public attribute names.
0093:             */
0094:            public static final String NAME = "x509";
0095:            public static final String INFO = X509CertInfo.NAME;
0096:            public static final String ALG_ID = "algorithm";
0097:            public static final String SIGNATURE = "signature";
0098:            public static final String SIGNED_CERT = "signed_cert";
0099:
0100:            /**
0101:             * The following are defined for ease-of-use. These
0102:             * are the most frequently retrieved attributes.
0103:             */
0104:            // x509.info.subject.dname
0105:            public static final String SUBJECT_DN = NAME + DOT + INFO + DOT
0106:                    + X509CertInfo.SUBJECT + DOT
0107:                    + CertificateSubjectName.DN_NAME;
0108:            // x509.info.issuer.dname
0109:            public static final String ISSUER_DN = NAME + DOT + INFO + DOT
0110:                    + X509CertInfo.ISSUER + DOT + CertificateIssuerName.DN_NAME;
0111:            // x509.info.serialNumber.number
0112:            public static final String SERIAL_ID = NAME + DOT + INFO + DOT
0113:                    + X509CertInfo.SERIAL_NUMBER + DOT
0114:                    + CertificateSerialNumber.NUMBER;
0115:            // x509.info.key.value
0116:            public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT
0117:                    + X509CertInfo.KEY + DOT + CertificateX509Key.KEY;
0118:
0119:            // x509.info.version.value
0120:            public static final String VERSION = NAME + DOT + INFO + DOT
0121:                    + X509CertInfo.VERSION + DOT + CertificateVersion.VERSION;
0122:
0123:            // x509.algorithm
0124:            public static final String SIG_ALG = NAME + DOT + ALG_ID;
0125:
0126:            // x509.signature
0127:            public static final String SIG = NAME + DOT + SIGNATURE;
0128:
0129:            // when we sign and decode we set this to true
0130:            // this is our means to make certificates immutable
0131:            private boolean readOnly = false;
0132:
0133:            // Certificate data, and its envelope
0134:            private byte[] signedCert = null;
0135:            protected X509CertInfo info = null;
0136:            protected AlgorithmId algId = null;
0137:            protected byte[] signature = null;
0138:
0139:            // recognized extension OIDS
0140:            private static final String KEY_USAGE_OID = "2.5.29.15";
0141:            private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
0142:            private static final String BASIC_CONSTRAINT_OID = "2.5.29.19";
0143:            private static final String SUBJECT_ALT_NAME_OID = "2.5.29.17";
0144:            private static final String ISSUER_ALT_NAME_OID = "2.5.29.18";
0145:
0146:            // number of standard key usage bits.
0147:            private static final int NUM_STANDARD_KEY_USAGE = 9;
0148:
0149:            // SubjectAlterntativeNames cache
0150:            private Collection subjectAlternativeNames;
0151:
0152:            // IssuerAlternativeNames cache
0153:            private Collection issuerAlternativeNames;
0154:
0155:            // ExtendedKeyUsage cache
0156:            private List extKeyUsage;
0157:
0158:            /**
0159:             * PublicKey that has previously been used to verify
0160:             * the signature of this certificate. Null if the certificate has not 
0161:             * yet been verified.
0162:             */
0163:            private PublicKey verifiedPublicKey;
0164:            /**
0165:             * If verifiedPublicKey is not null, name of the provider used to
0166:             * successfully verify the signature of this certificate, or the
0167:             * empty String if no provider was explicitly specified.
0168:             */
0169:            private String verifiedProvider;
0170:            /**
0171:             * If verifiedPublicKey is not null, result of the verification using
0172:             * verifiedPublicKey and verifiedProvider. If true, verification was
0173:             * successful, if false, it failed.
0174:             */
0175:            private boolean verificationResult;
0176:
0177:            /**
0178:             * Default constructor.
0179:             */
0180:            public X509CertImpl() {
0181:            }
0182:
0183:            /**
0184:             * Unmarshals a certificate from its encoded form, parsing the
0185:             * encoded bytes.  This form of constructor is used by agents which
0186:             * need to examine and use certificate contents.  That is, this is
0187:             * one of the more commonly used constructors.  Note that the buffer
0188:             * must include only a certificate, and no "garbage" may be left at
0189:             * the end.  If you need to ignore data at the end of a certificate,
0190:             * use another constructor.
0191:             *
0192:             * @param certData the encoded bytes, with no trailing padding.
0193:             * @exception CertificateException on parsing and initialization errors.
0194:             */
0195:            public X509CertImpl(byte[] certData) throws CertificateException {
0196:                try {
0197:                    parse(new DerValue(certData));
0198:                } catch (IOException e) {
0199:                    signedCert = null;
0200:                    CertificateException ce = new CertificateException(
0201:                            "Unable to initialize, " + e);
0202:                    ce.initCause(e);
0203:                    throw ce;
0204:                }
0205:            }
0206:
0207:            /**
0208:             * unmarshals an X.509 certificate from an input stream.  If the
0209:             * certificate is RFC1421 hex-encoded, then it must begin with
0210:             * the line X509Factory.BEGIN_CERT and end with the line
0211:             * X509Factory.END_CERT.
0212:             *
0213:             * @param in an input stream holding at least one certificate that may
0214:             *        be either DER-encoded or RFC1421 hex-encoded version of the
0215:             *        DER-encoded certificate.
0216:             * @exception CertificateException on parsing and initialization errors.
0217:             */
0218:            public X509CertImpl(InputStream in) throws CertificateException {
0219:
0220:                DerValue der = null;
0221:
0222:                BufferedInputStream inBuffered = new BufferedInputStream(in);
0223:
0224:                // First try reading stream as HEX-encoded DER-encoded bytes, 
0225:                // since not mistakable for raw DER
0226:                try {
0227:                    inBuffered.mark(Integer.MAX_VALUE);
0228:                    der = readRFC1421Cert(inBuffered);
0229:                } catch (IOException ioe) {
0230:                    try {
0231:                        // Next, try reading stream as raw DER-encoded bytes
0232:                        inBuffered.reset();
0233:                        der = new DerValue(inBuffered);
0234:                    } catch (IOException ioe1) {
0235:                        CertificateException ce = new CertificateException(
0236:                                "Input stream must be "
0237:                                        + "either DER-encoded bytes "
0238:                                        + "or RFC1421 hex-encoded "
0239:                                        + "DER-encoded bytes: "
0240:                                        + ioe1.getMessage());
0241:                        ce.initCause(ioe1);
0242:                        throw ce;
0243:                    }
0244:                }
0245:                try {
0246:                    parse(der);
0247:                } catch (IOException ioe) {
0248:                    signedCert = null;
0249:                    CertificateException ce = new CertificateException(
0250:                            "Unable to parse DER value of " + "certificate, "
0251:                                    + ioe);
0252:                    ce.initCause(ioe);
0253:                    throw ce;
0254:                }
0255:            }
0256:
0257:            /**
0258:             * read input stream as HEX-encoded DER-encoded bytes
0259:             *
0260:             * @param in InputStream to read
0261:             * @returns DerValue corresponding to decoded HEX-encoded bytes
0262:             * @throws IOException if stream can not be interpreted as RFC1421 
0263:             *                     encoded bytes
0264:             */
0265:            private DerValue readRFC1421Cert(InputStream in) throws IOException {
0266:                DerValue der = null;
0267:                String line = null;
0268:                BufferedReader certBufferedReader = new BufferedReader(
0269:                        new InputStreamReader(in));
0270:                try {
0271:                    line = certBufferedReader.readLine();
0272:                } catch (IOException ioe1) {
0273:                    throw new IOException("Unable to read InputStream: "
0274:                            + ioe1.getMessage());
0275:                }
0276:                if (line.equals(X509Factory.BEGIN_CERT)) {
0277:                    /* stream appears to be hex-encoded bytes */
0278:                    BASE64Decoder decoder = new BASE64Decoder();
0279:                    ByteArrayOutputStream decstream = new ByteArrayOutputStream();
0280:                    try {
0281:                        while ((line = certBufferedReader.readLine()) != null) {
0282:                            if (line.equals(X509Factory.END_CERT)) {
0283:                                der = new DerValue(decstream.toByteArray());
0284:                                break;
0285:                            } else {
0286:                                decstream.write(decoder.decodeBuffer(line));
0287:                            }
0288:                        }
0289:                    } catch (IOException ioe2) {
0290:                        throw new IOException("Unable to read InputStream: "
0291:                                + ioe2.getMessage());
0292:                    }
0293:                } else {
0294:                    throw new IOException(
0295:                            "InputStream is not RFC1421 hex-encoded "
0296:                                    + "DER bytes");
0297:                }
0298:                return der;
0299:            }
0300:
0301:            /**
0302:             * Construct an initialized X509 Certificate. The certificate is stored
0303:             * in raw form and has to be signed to be useful.
0304:             *   
0305:             * @params info the X509CertificateInfo which the Certificate is to be
0306:             *              created from.
0307:             */
0308:            public X509CertImpl(X509CertInfo certInfo) {
0309:                this .info = certInfo;
0310:            }
0311:
0312:            /**
0313:             * Unmarshal a certificate from its encoded form, parsing a DER value.
0314:             * This form of constructor is used by agents which need to examine
0315:             * and use certificate contents.
0316:             *   
0317:             * @param derVal the der value containing the encoded cert.
0318:             * @exception CertificateException on parsing and initialization errors.
0319:             */
0320:            public X509CertImpl(DerValue derVal) throws CertificateException {
0321:                try {
0322:                    parse(derVal);
0323:                } catch (IOException e) {
0324:                    signedCert = null;
0325:                    CertificateException ce = new CertificateException(
0326:                            "Unable to initialize, " + e);
0327:                    ce.initCause(e);
0328:                    throw ce;
0329:                }
0330:            }
0331:
0332:            /**
0333:             * Appends the certificate to an output stream.
0334:             *
0335:             * @param out an input stream to which the certificate is appended.
0336:             * @exception CertificateEncodingException on encoding errors.
0337:             */
0338:            public void encode(OutputStream out)
0339:                    throws CertificateEncodingException {
0340:                if (signedCert == null)
0341:                    throw new CertificateEncodingException(
0342:                            "Null certificate to encode");
0343:                try {
0344:                    out.write((byte[]) signedCert.clone());
0345:                } catch (IOException e) {
0346:                    throw new CertificateEncodingException(e.toString());
0347:                }
0348:            }
0349:
0350:            /**
0351:             * DER encode this object onto an output stream.
0352:             * Implements the <code>DerEncoder</code> interface.
0353:             *
0354:             * @param out the output stream on which to write the DER encoding.
0355:             *
0356:             * @exception IOException on encoding error.
0357:             */
0358:            public void derEncode(OutputStream out) throws IOException {
0359:                if (signedCert == null)
0360:                    throw new IOException("Null certificate to encode");
0361:                out.write((byte[]) signedCert.clone());
0362:            }
0363:
0364:            /**
0365:             * Returns the encoded form of this certificate. It is
0366:             * assumed that each certificate type would have only a single
0367:             * form of encoding; for example, X.509 certificates would
0368:             * be encoded as ASN.1 DER.
0369:             *   
0370:             * @exception CertificateEncodingException if an encoding error occurs.
0371:             */
0372:            public byte[] getEncoded() throws CertificateEncodingException {
0373:                return (byte[]) getEncodedInternal().clone();
0374:            }
0375:
0376:            /**
0377:             * Returned the encoding as an uncloned byte array. Callers must
0378:             * guarantee that they neither modify it nor expose it to untrusted
0379:             * code.
0380:             */
0381:            public byte[] getEncodedInternal()
0382:                    throws CertificateEncodingException {
0383:                if (signedCert == null) {
0384:                    throw new CertificateEncodingException(
0385:                            "Null certificate to encode");
0386:                }
0387:                return signedCert;
0388:            }
0389:
0390:            /**
0391:             * Throws an exception if the certificate was not signed using the
0392:             * verification key provided.  Successfully verifying a certificate
0393:             * does <em>not</em> indicate that one should trust the entity which
0394:             * it represents.
0395:             *
0396:             * @param key the public key used for verification.
0397:             *   
0398:             * @exception InvalidKeyException on incorrect key.
0399:             * @exception NoSuchAlgorithmException on unsupported signature
0400:             * algorithms.
0401:             * @exception NoSuchProviderException if there's no default provider.
0402:             * @exception SignatureException on signature errors.
0403:             * @exception CertificateException on encoding errors.
0404:             */
0405:            public void verify(PublicKey key) throws CertificateException,
0406:                    NoSuchAlgorithmException, InvalidKeyException,
0407:                    NoSuchProviderException, SignatureException {
0408:
0409:                verify(key, "");
0410:            }
0411:
0412:            /**
0413:             * Throws an exception if the certificate was not signed using the
0414:             * verification key provided.  Successfully verifying a certificate
0415:             * does <em>not</em> indicate that one should trust the entity which
0416:             * it represents.
0417:             *
0418:             * @param key the public key used for verification.
0419:             * @param sigProvider the name of the provider.
0420:             *   
0421:             * @exception NoSuchAlgorithmException on unsupported signature
0422:             * algorithms.
0423:             * @exception InvalidKeyException on incorrect key.
0424:             * @exception NoSuchProviderException on incorrect provider.
0425:             * @exception SignatureException on signature errors.
0426:             * @exception CertificateException on encoding errors.
0427:             */
0428:            public synchronized void verify(PublicKey key, String sigProvider)
0429:                    throws CertificateException, NoSuchAlgorithmException,
0430:                    InvalidKeyException, NoSuchProviderException,
0431:                    SignatureException {
0432:                if (sigProvider == null) {
0433:                    sigProvider = "";
0434:                }
0435:                if ((verifiedPublicKey != null)
0436:                        && verifiedPublicKey.equals(key)) {
0437:                    // this certificate has already been verified using
0438:                    // this public key. Make sure providers match, too.
0439:                    if (sigProvider.equals(verifiedProvider)) {
0440:                        if (verificationResult) {
0441:                            return;
0442:                        } else {
0443:                            throw new SignatureException(
0444:                                    "Signature does not match.");
0445:                        }
0446:                    }
0447:                }
0448:                if (signedCert == null) {
0449:                    throw new CertificateEncodingException(
0450:                            "Uninitialized certificate");
0451:                }
0452:                // Verify the signature ...
0453:                Signature sigVerf = null;
0454:                if (sigProvider.length() == 0) {
0455:                    sigVerf = Signature.getInstance(algId.getName());
0456:                } else {
0457:                    sigVerf = Signature.getInstance(algId.getName(),
0458:                            sigProvider);
0459:                }
0460:                sigVerf.initVerify(key);
0461:
0462:                byte[] rawCert = info.getEncodedInfo();
0463:                sigVerf.update(rawCert, 0, rawCert.length);
0464:
0465:                // verify may throw SignatureException for invalid encodings, etc.
0466:                verificationResult = sigVerf.verify(signature);
0467:                verifiedPublicKey = key;
0468:                verifiedProvider = sigProvider;
0469:
0470:                if (verificationResult == false) {
0471:                    throw new SignatureException("Signature does not match.");
0472:                }
0473:            }
0474:
0475:            /**
0476:             * Creates an X.509 certificate, and signs it using the given key
0477:             * (associating a signature algorithm and an X.500 name).
0478:             * This operation is used to implement the certificate generation
0479:             * functionality of a certificate authority.
0480:             *
0481:             * @param key the private key used for signing.
0482:             * @param algorithm the name of the signature algorithm used.
0483:             *
0484:             * @exception InvalidKeyException on incorrect key.
0485:             * @exception NoSuchAlgorithmException on unsupported signature
0486:             * algorithms.
0487:             * @exception NoSuchProviderException if there's no default provider.
0488:             * @exception SignatureException on signature errors.
0489:             * @exception CertificateException on encoding errors.
0490:             */
0491:            public void sign(PrivateKey key, String algorithm)
0492:                    throws CertificateException, NoSuchAlgorithmException,
0493:                    InvalidKeyException, NoSuchProviderException,
0494:                    SignatureException {
0495:                sign(key, algorithm, null);
0496:            }
0497:
0498:            /**
0499:             * Creates an X.509 certificate, and signs it using the given key
0500:             * (associating a signature algorithm and an X.500 name).
0501:             * This operation is used to implement the certificate generation
0502:             * functionality of a certificate authority.
0503:             *
0504:             * @param key the private key used for signing.
0505:             * @param algorithm the name of the signature algorithm used.
0506:             * @param provider the name of the provider.
0507:             *
0508:             * @exception NoSuchAlgorithmException on unsupported signature
0509:             * algorithms.
0510:             * @exception InvalidKeyException on incorrect key.
0511:             * @exception NoSuchProviderException on incorrect provider.
0512:             * @exception SignatureException on signature errors.
0513:             * @exception CertificateException on encoding errors.
0514:             */
0515:            public void sign(PrivateKey key, String algorithm, String provider)
0516:                    throws CertificateException, NoSuchAlgorithmException,
0517:                    InvalidKeyException, NoSuchProviderException,
0518:                    SignatureException {
0519:                try {
0520:                    if (readOnly)
0521:                        throw new CertificateEncodingException(
0522:                                "cannot over-write existing certificate");
0523:                    Signature sigEngine = null;
0524:                    if ((provider == null) || (provider.length() == 0))
0525:                        sigEngine = Signature.getInstance(algorithm);
0526:                    else
0527:                        sigEngine = Signature.getInstance(algorithm, provider);
0528:
0529:                    sigEngine.initSign(key);
0530:
0531:                    // in case the name is reset
0532:                    algId = AlgorithmId.get(sigEngine.getAlgorithm());
0533:
0534:                    DerOutputStream out = new DerOutputStream();
0535:                    DerOutputStream tmp = new DerOutputStream();
0536:
0537:                    // encode certificate info
0538:                    info.encode(tmp);
0539:                    byte[] rawCert = tmp.toByteArray();
0540:
0541:                    // encode algorithm identifier
0542:                    algId.encode(tmp);
0543:
0544:                    // Create and encode the signature itself.
0545:                    sigEngine.update(rawCert, 0, rawCert.length);
0546:                    signature = sigEngine.sign();
0547:                    tmp.putBitString(signature);
0548:
0549:                    // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
0550:                    out.write(DerValue.tag_Sequence, tmp);
0551:                    signedCert = out.toByteArray();
0552:                    readOnly = true;
0553:
0554:                } catch (IOException e) {
0555:                    throw new CertificateEncodingException(e.toString());
0556:                }
0557:            }
0558:
0559:            /**
0560:             * Checks that the certificate is currently valid, i.e. the current
0561:             * time is within the specified validity period.
0562:             * 
0563:             * @exception CertificateExpiredException if the certificate has expired.
0564:             * @exception CertificateNotYetValidException if the certificate is not
0565:             * yet valid.
0566:             */
0567:            public void checkValidity() throws CertificateExpiredException,
0568:                    CertificateNotYetValidException {
0569:                Date date = new Date();
0570:                checkValidity(date);
0571:            }
0572:
0573:            /**
0574:             * Checks that the specified date is within the certificate's 
0575:             * validity period, or basically if the certificate would be 
0576:             * valid at the specified date/time. 
0577:             * 
0578:             * @param date the Date to check against to see if this certificate
0579:             *        is valid at that date/time.
0580:             *
0581:             * @exception CertificateExpiredException if the certificate has expired
0582:             * with respect to the <code>date</code> supplied.
0583:             * @exception CertificateNotYetValidException if the certificate is not
0584:             * yet valid with respect to the <code>date</code> supplied.
0585:             */
0586:            public void checkValidity(Date date)
0587:                    throws CertificateExpiredException,
0588:                    CertificateNotYetValidException {
0589:
0590:                CertificateValidity interval = null;
0591:                try {
0592:                    interval = (CertificateValidity) info
0593:                            .get(CertificateValidity.NAME);
0594:                } catch (Exception e) {
0595:                    throw new CertificateNotYetValidException(
0596:                            "Incorrect validity period");
0597:                }
0598:                if (interval == null)
0599:                    throw new CertificateNotYetValidException(
0600:                            "Null validity period");
0601:                interval.valid(date);
0602:            }
0603:
0604:            /**
0605:             * Return the requested attribute from the certificate.
0606:             *
0607:             * Note that the X509CertInfo is not cloned for performance reasons.
0608:             * Callers must ensure that they do not modify it. All other
0609:             * attributes are cloned.
0610:             *
0611:             * @param name the name of the attribute.
0612:             * @exception CertificateParsingException on invalid attribute identifier.
0613:             */
0614:            public Object get(String name) throws CertificateParsingException {
0615:                X509AttributeName attr = new X509AttributeName(name);
0616:                String id = attr.getPrefix();
0617:                if (!(id.equalsIgnoreCase(NAME))) {
0618:                    throw new CertificateParsingException("Invalid root of "
0619:                            + "attribute name, expected [" + NAME
0620:                            + "], received " + "[" + id + "]");
0621:                }
0622:                attr = new X509AttributeName(attr.getSuffix());
0623:                id = attr.getPrefix();
0624:
0625:                if (id.equalsIgnoreCase(INFO)) {
0626:                    if (info == null) {
0627:                        return null;
0628:                    }
0629:                    if (attr.getSuffix() != null) {
0630:                        try {
0631:                            return info.get(attr.getSuffix());
0632:                        } catch (IOException e) {
0633:                            throw new CertificateParsingException(e.toString());
0634:                        } catch (CertificateException e) {
0635:                            throw new CertificateParsingException(e.toString());
0636:                        }
0637:                    } else {
0638:                        return info;
0639:                    }
0640:                } else if (id.equalsIgnoreCase(ALG_ID)) {
0641:                    return (algId);
0642:                } else if (id.equalsIgnoreCase(SIGNATURE)) {
0643:                    if (signature != null)
0644:                        return signature.clone();
0645:                    else
0646:                        return null;
0647:                } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
0648:                    if (signedCert != null)
0649:                        return signedCert.clone();
0650:                    else
0651:                        return null;
0652:                } else {
0653:                    throw new CertificateParsingException("Attribute name not "
0654:                            + "recognized or get() not allowed for the same: "
0655:                            + id);
0656:                }
0657:            }
0658:
0659:            /**
0660:             * Set the requested attribute in the certificate.
0661:             *
0662:             * @param name the name of the attribute.
0663:             * @param obj the value of the attribute.
0664:             * @exception CertificateException on invalid attribute identifier.
0665:             * @exception IOException on encoding error of attribute.
0666:             */
0667:            public void set(String name, Object obj)
0668:                    throws CertificateException, IOException {
0669:                // check if immutable
0670:                if (readOnly)
0671:                    throw new CertificateException("cannot over-write existing"
0672:                            + " certificate");
0673:
0674:                X509AttributeName attr = new X509AttributeName(name);
0675:                String id = attr.getPrefix();
0676:                if (!(id.equalsIgnoreCase(NAME))) {
0677:                    throw new CertificateException(
0678:                            "Invalid root of attribute name," + " expected ["
0679:                                    + NAME + "], received " + id);
0680:                }
0681:                attr = new X509AttributeName(attr.getSuffix());
0682:                id = attr.getPrefix();
0683:
0684:                if (id.equalsIgnoreCase(INFO)) {
0685:                    if (attr.getSuffix() == null) {
0686:                        if (!(obj instanceof  X509CertInfo)) {
0687:                            throw new CertificateException(
0688:                                    "Attribute value should"
0689:                                            + " be of type X509CertInfo.");
0690:                        }
0691:                        info = (X509CertInfo) obj;
0692:                        signedCert = null; //reset this as certificate data has changed
0693:                    } else {
0694:                        info.set(attr.getSuffix(), obj);
0695:                        signedCert = null; //reset this as certificate data has changed
0696:                    }
0697:                } else {
0698:                    throw new CertificateException(
0699:                            "Attribute name not recognized or "
0700:                                    + "set() not allowed for the same: " + id);
0701:                }
0702:            }
0703:
0704:            /**
0705:             * Delete the requested attribute from the certificate.
0706:             *
0707:             * @param name the name of the attribute.
0708:             * @exception CertificateException on invalid attribute identifier.
0709:             * @exception IOException on other errors.
0710:             */
0711:            public void delete(String name) throws CertificateException,
0712:                    IOException {
0713:                // check if immutable
0714:                if (readOnly)
0715:                    throw new CertificateException("cannot over-write existing"
0716:                            + " certificate");
0717:
0718:                X509AttributeName attr = new X509AttributeName(name);
0719:                String id = attr.getPrefix();
0720:                if (!(id.equalsIgnoreCase(NAME))) {
0721:                    throw new CertificateException(
0722:                            "Invalid root of attribute name," + " expected ["
0723:                                    + NAME + "], received " + id);
0724:                }
0725:                attr = new X509AttributeName(attr.getSuffix());
0726:                id = attr.getPrefix();
0727:
0728:                if (id.equalsIgnoreCase(INFO)) {
0729:                    if (attr.getSuffix() != null) {
0730:                        info = null;
0731:                    } else {
0732:                        info.delete(attr.getSuffix());
0733:                    }
0734:                } else if (id.equalsIgnoreCase(ALG_ID)) {
0735:                    algId = null;
0736:                } else if (id.equalsIgnoreCase(SIGNATURE)) {
0737:                    signature = null;
0738:                } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
0739:                    signedCert = null;
0740:                } else {
0741:                    throw new CertificateException(
0742:                            "Attribute name not recognized or "
0743:                                    + "delete() not allowed for the same: "
0744:                                    + id);
0745:                }
0746:            }
0747:
0748:            /**
0749:             * Return an enumeration of names of attributes existing within this
0750:             * attribute.
0751:             */
0752:            public Enumeration getElements() {
0753:                AttributeNameEnumeration elements = new AttributeNameEnumeration();
0754:                elements.addElement(NAME + DOT + INFO);
0755:                elements.addElement(NAME + DOT + ALG_ID);
0756:                elements.addElement(NAME + DOT + SIGNATURE);
0757:                elements.addElement(NAME + DOT + SIGNED_CERT);
0758:
0759:                return (elements.elements());
0760:            }
0761:
0762:            /**
0763:             * Return the name of this attribute.
0764:             */
0765:            public String getName() {
0766:                return (NAME);
0767:            }
0768:
0769:            /**
0770:             * Returns a printable representation of the certificate.  This does not
0771:             * contain all the information available to distinguish this from any
0772:             * other certificate.  The certificate must be fully constructed
0773:             * before this function may be called.
0774:             */
0775:            public String toString() {
0776:                if (info == null || algId == null || signature == null)
0777:                    return "";
0778:
0779:                StringBuffer sb = new StringBuffer();
0780:
0781:                sb.append("[\n");
0782:                sb.append(info.toString() + "\n");
0783:                sb.append("  Algorithm: [" + algId.toString() + "]\n");
0784:
0785:                HexDumpEncoder encoder = new HexDumpEncoder();
0786:                sb.append("  Signature:\n" + encoder.encodeBuffer(signature));
0787:                sb.append("\n]");
0788:
0789:                return sb.toString();
0790:            }
0791:
0792:            // the strongly typed gets, as per java.security.cert.X509Certificate
0793:
0794:            /**
0795:             * Gets the publickey from this certificate.
0796:             *   
0797:             * @return the publickey.
0798:             */
0799:            public PublicKey getPublicKey() {
0800:                if (info == null)
0801:                    return null;
0802:                try {
0803:                    PublicKey key = (PublicKey) info
0804:                            .get(CertificateX509Key.NAME + DOT
0805:                                    + CertificateX509Key.KEY);
0806:                    return key;
0807:                } catch (Exception e) {
0808:                    return null;
0809:                }
0810:            }
0811:
0812:            /**
0813:             * Gets the version number from the certificate.
0814:             *
0815:             * @return the version number, i.e. 1, 2 or 3.
0816:             */
0817:            public int getVersion() {
0818:                if (info == null)
0819:                    return -1;
0820:                try {
0821:                    int vers = ((Integer) info.get(CertificateVersion.NAME
0822:                            + DOT + CertificateVersion.VERSION)).intValue();
0823:                    return vers + 1;
0824:                } catch (Exception e) {
0825:                    return -1;
0826:                }
0827:            }
0828:
0829:            /**
0830:             * Gets the serial number from the certificate.
0831:             *
0832:             * @return the serial number.
0833:             */
0834:            public BigInteger getSerialNumber() {
0835:                if (info == null)
0836:                    return null;
0837:                try {
0838:                    SerialNumber ser = (SerialNumber) info
0839:                            .get(CertificateSerialNumber.NAME + DOT
0840:                                    + CertificateSerialNumber.NUMBER);
0841:                    return ser.getNumber();
0842:                } catch (Exception e) {
0843:                    return null;
0844:                }
0845:            }
0846:
0847:            /**
0848:             * Gets the subject distinguished name from the certificate.
0849:             *
0850:             * @return the subject name.
0851:             */
0852:            public Principal getSubjectDN() {
0853:                if (info == null)
0854:                    return null;
0855:                try {
0856:                    Principal subject = (Principal) info
0857:                            .get(CertificateSubjectName.NAME + DOT
0858:                                    + CertificateSubjectName.DN_NAME);
0859:                    return subject;
0860:                } catch (Exception e) {
0861:                    return null;
0862:                }
0863:            }
0864:
0865:            /**
0866:             * Get subject name as X500Principal. Overrides implementation in
0867:             * X509Certificate with a slightly more efficient version that is
0868:             * also aware of X509CertImpl mutability.
0869:             */
0870:            public X500Principal getSubjectX500Principal() {
0871:                if (info == null) {
0872:                    return null;
0873:                }
0874:                try {
0875:                    X500Principal subject = (X500Principal) info
0876:                            .get(CertificateSubjectName.NAME + DOT
0877:                                    + CertificateSubjectName.DN_PRINCIPAL);
0878:                    return subject;
0879:                } catch (Exception e) {
0880:                    return null;
0881:                }
0882:            }
0883:
0884:            /**
0885:             * Gets the issuer distinguished name from the certificate.
0886:             *
0887:             * @return the issuer name.
0888:             */
0889:            public Principal getIssuerDN() {
0890:                if (info == null)
0891:                    return null;
0892:                try {
0893:                    Principal issuer = (Principal) info
0894:                            .get(CertificateIssuerName.NAME + DOT
0895:                                    + CertificateIssuerName.DN_NAME);
0896:                    return issuer;
0897:                } catch (Exception e) {
0898:                    return null;
0899:                }
0900:            }
0901:
0902:            /**
0903:             * Get issuer name as X500Principal. Overrides implementation in
0904:             * X509Certificate with a slightly more efficient version that is
0905:             * also aware of X509CertImpl mutability.
0906:             */
0907:            public X500Principal getIssuerX500Principal() {
0908:                if (info == null) {
0909:                    return null;
0910:                }
0911:                try {
0912:                    X500Principal issuer = (X500Principal) info
0913:                            .get(CertificateIssuerName.NAME + DOT
0914:                                    + CertificateIssuerName.DN_PRINCIPAL);
0915:                    return issuer;
0916:                } catch (Exception e) {
0917:                    return null;
0918:                }
0919:            }
0920:
0921:            /**
0922:             * Gets the notBefore date from the validity period of the certificate.
0923:             *
0924:             * @return the start date of the validity period.
0925:             */
0926:            public Date getNotBefore() {
0927:                if (info == null)
0928:                    return null;
0929:                try {
0930:                    Date d = (Date) info.get(CertificateValidity.NAME + DOT
0931:                            + CertificateValidity.NOT_BEFORE);
0932:                    return d;
0933:                } catch (Exception e) {
0934:                    return null;
0935:                }
0936:            }
0937:
0938:            /**
0939:             * Gets the notAfter date from the validity period of the certificate.
0940:             *
0941:             * @return the end date of the validity period.
0942:             */
0943:            public Date getNotAfter() {
0944:                if (info == null)
0945:                    return null;
0946:                try {
0947:                    Date d = (Date) info.get(CertificateValidity.NAME + DOT
0948:                            + CertificateValidity.NOT_AFTER);
0949:                    return d;
0950:                } catch (Exception e) {
0951:                    return null;
0952:                }
0953:            }
0954:
0955:            /**
0956:             * Gets the DER encoded certificate informations, the
0957:             * <code>tbsCertificate</code> from this certificate. 
0958:             * This can be used to verify the signature independently.   
0959:             *   
0960:             * @return the DER encoded certificate information.
0961:             * @exception CertificateEncodingException if an encoding error occurs.
0962:             */
0963:            public byte[] getTBSCertificate()
0964:                    throws CertificateEncodingException {
0965:                if (info != null) {
0966:                    return info.getEncodedInfo();
0967:                } else
0968:                    throw new CertificateEncodingException(
0969:                            "Uninitialized certificate");
0970:            }
0971:
0972:            /**
0973:             * Gets the raw Signature bits from the certificate.
0974:             *
0975:             * @return the signature.
0976:             */
0977:            public byte[] getSignature() {
0978:                if (signature == null)
0979:                    return null;
0980:                byte[] dup = new byte[signature.length];
0981:                System.arraycopy(signature, 0, dup, 0, dup.length);
0982:                return dup;
0983:            }
0984:
0985:            /**
0986:             * Gets the signature algorithm name for the certificate
0987:             * signature algorithm.
0988:             * For example, the string "SHA-1/DSA" or "DSS".
0989:             *
0990:             * @return the signature algorithm name.
0991:             */
0992:            public String getSigAlgName() {
0993:                if (algId == null)
0994:                    return null;
0995:                return (algId.getName());
0996:            }
0997:
0998:            /**
0999:             * Gets the signature algorithm OID string from the certificate.
1000:             * For example, the string "1.2.840.10040.4.3"
1001:             *
1002:             * @return the signature algorithm oid string.
1003:             */
1004:            public String getSigAlgOID() {
1005:                if (algId == null)
1006:                    return null;
1007:                ObjectIdentifier oid = algId.getOID();
1008:                return (oid.toString());
1009:            }
1010:
1011:            /**
1012:             * Gets the DER encoded signature algorithm parameters from this
1013:             * certificate's signature algorithm.
1014:             *   
1015:             * @return the DER encoded signature algorithm parameters, or
1016:             *         null if no parameters are present.
1017:             */
1018:            public byte[] getSigAlgParams() {
1019:                if (algId == null)
1020:                    return null;
1021:                try {
1022:                    return algId.getEncodedParams();
1023:                } catch (IOException e) {
1024:                    return null;
1025:                }
1026:            }
1027:
1028:            /**
1029:             * Gets the Issuer Unique Identity from the certificate.
1030:             *
1031:             * @return the Issuer Unique Identity.
1032:             */
1033:            public boolean[] getIssuerUniqueID() {
1034:                if (info == null)
1035:                    return null;
1036:                try {
1037:                    UniqueIdentity id = (UniqueIdentity) info
1038:                            .get(CertificateIssuerUniqueIdentity.NAME + DOT
1039:                                    + CertificateIssuerUniqueIdentity.ID);
1040:                    if (id == null)
1041:                        return null;
1042:                    else
1043:                        return (id.getId());
1044:                } catch (Exception e) {
1045:                    return null;
1046:                }
1047:            }
1048:
1049:            /**
1050:             * Gets the Subject Unique Identity from the certificate.
1051:             *
1052:             * @return the Subject Unique Identity.
1053:             */
1054:            public boolean[] getSubjectUniqueID() {
1055:                if (info == null)
1056:                    return null;
1057:                try {
1058:                    UniqueIdentity id = (UniqueIdentity) info
1059:                            .get(CertificateSubjectUniqueIdentity.NAME + DOT
1060:                                    + CertificateSubjectUniqueIdentity.ID);
1061:                    if (id == null)
1062:                        return null;
1063:                    else
1064:                        return (id.getId());
1065:                } catch (Exception e) {
1066:                    return null;
1067:                }
1068:            }
1069:
1070:            /**
1071:             * Get AuthorityKeyIdentifier extension
1072:             * @return AuthorityKeyIdentifier object or null (if no such object 
1073:             * in certificate)
1074:             */
1075:            public AuthorityKeyIdentifierExtension getAuthorityKeyIdentifierExtension() {
1076:                return (AuthorityKeyIdentifierExtension) getExtension(PKIXExtensions.AuthorityKey_Id);
1077:            }
1078:
1079:            /**
1080:             * Get BasicConstraints extension
1081:             * @return BasicConstraints object or null (if no such object in 
1082:             * certificate)
1083:             */
1084:            public BasicConstraintsExtension getBasicConstraintsExtension() {
1085:                return (BasicConstraintsExtension) getExtension(PKIXExtensions.BasicConstraints_Id);
1086:            }
1087:
1088:            /**
1089:             * Get CertificatePoliciesExtension
1090:             * @return CertificatePoliciesExtension or null (if no such object in 
1091:             * certificate)
1092:             * CDC/FP Subsets away CertificatePoliciesExtension.
1093:            public CertificatePoliciesExtension getCertificatePoliciesExtension() {
1094:            return (CertificatePoliciesExtension)
1095:                getExtension(PKIXExtensions.CertificatePolicies_Id);
1096:            }
1097:             */
1098:
1099:            /**
1100:             * Get ExtendedKeyUsage extension
1101:             * @return ExtendedKeyUsage extension object or null (if no such object 
1102:             * in certificate)
1103:             */
1104:            public ExtendedKeyUsageExtension getExtendedKeyUsageExtension() {
1105:                return (ExtendedKeyUsageExtension) getExtension(PKIXExtensions.ExtendedKeyUsage_Id);
1106:            }
1107:
1108:            /**
1109:             * Get IssuerAlternativeName extension
1110:             * @return IssuerAlternativeName object or null (if no such object in 
1111:             * certificate)
1112:             */
1113:            public IssuerAlternativeNameExtension getIssuerAlternativeNameExtension() {
1114:                return (IssuerAlternativeNameExtension) getExtension(PKIXExtensions.IssuerAlternativeName_Id);
1115:            }
1116:
1117:            /**
1118:             * Get NameConstraints extension
1119:             * @return NameConstraints object or null (if no such object in certificate)
1120:             */
1121:            public NameConstraintsExtension getNameConstraintsExtension() {
1122:                return (NameConstraintsExtension) getExtension(PKIXExtensions.NameConstraints_Id);
1123:            }
1124:
1125:            /**
1126:             * Get PolicyConstraints extension
1127:             * @return PolicyConstraints object or null (if no such object in 
1128:             * certificate)
1129:             */
1130:            public PolicyConstraintsExtension getPolicyConstraintsExtension() {
1131:                return (PolicyConstraintsExtension) getExtension(PKIXExtensions.PolicyConstraints_Id);
1132:            }
1133:
1134:            /**
1135:             * Get PolicyMappingsExtension extension
1136:             * @return PolicyMappingsExtension object or null (if no such object 
1137:             * in certificate)
1138:             */
1139:            public PolicyMappingsExtension getPolicyMappingsExtension() {
1140:                return (PolicyMappingsExtension) getExtension(PKIXExtensions.PolicyMappings_Id);
1141:            }
1142:
1143:            /**
1144:             * Get PrivateKeyUsage extension
1145:             * @return PrivateKeyUsage object or null (if no such object in certificate)
1146:             */
1147:            public PrivateKeyUsageExtension getPrivateKeyUsageExtension() {
1148:                return (PrivateKeyUsageExtension) getExtension(PKIXExtensions.PrivateKeyUsage_Id);
1149:            }
1150:
1151:            /**
1152:             * Get SubjectAlternativeName extension
1153:             * @return SubjectAlternativeName object or null (if no such object in 
1154:             * certificate)
1155:             */
1156:            public SubjectAlternativeNameExtension getSubjectAlternativeNameExtension() {
1157:                return (SubjectAlternativeNameExtension) getExtension(PKIXExtensions.SubjectAlternativeName_Id);
1158:            }
1159:
1160:            /**
1161:             * Get SubjectKeyIdentifier extension
1162:             * @return SubjectKeyIdentifier object or null (if no such object in 
1163:             * certificate)
1164:             */
1165:            public SubjectKeyIdentifierExtension getSubjectKeyIdentifierExtension() {
1166:                return (SubjectKeyIdentifierExtension) getExtension(PKIXExtensions.SubjectKey_Id);
1167:            }
1168:
1169:            /**
1170:             * Get CRLDistributionPoints extension
1171:             * @return CRLDistributionPoints object or null (if no such object in 
1172:             * certificate)
1173:             * CDC/FP moves CRLDistributionPointsExtension to the
1174:             * security optional package.
1175:            public CRLDistributionPointsExtension getCRLDistributionPointsExtension() {
1176:            return (CRLDistributionPointsExtension)
1177:                getExtension(PKIXExtensions.CRLDistributionPoints_Id);
1178:            }
1179:             */
1180:
1181:            /** 
1182:             * Return true if a critical extension is found that is
1183:             * not supported, otherwise return false. 
1184:             */
1185:            public boolean hasUnsupportedCriticalExtension() {
1186:                if (info == null)
1187:                    return false;
1188:                try {
1189:                    CertificateExtensions exts = (CertificateExtensions) info
1190:                            .get(CertificateExtensions.NAME);
1191:                    if (exts == null)
1192:                        return false;
1193:                    return exts.hasUnsupportedCriticalExtension();
1194:                } catch (Exception e) {
1195:                    return false;
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Gets a Set of the extension(s) marked CRITICAL in the
1201:             * certificate. In the returned set, each extension is
1202:             * represented by its OID string.
1203:             *   
1204:             * @return a set of the extension oid strings in the
1205:             * certificate that are marked critical.
1206:             */
1207:            public Set getCriticalExtensionOIDs() {
1208:                if (info == null)
1209:                    return null;
1210:                try {
1211:                    CertificateExtensions exts = (CertificateExtensions) info
1212:                            .get(CertificateExtensions.NAME);
1213:                    if (exts == null)
1214:                        return null;
1215:                    HashSet extSet = new HashSet(11);
1216:                    Extension ex;
1217:                    for (Enumeration e = exts.getElements(); e
1218:                            .hasMoreElements();) {
1219:                        ex = (Extension) e.nextElement();
1220:                        if (ex.isCritical())
1221:                            extSet.add(((ObjectIdentifier) ex.getExtensionId())
1222:                                    .toString());
1223:                    }
1224:                    return extSet;
1225:                } catch (Exception e) {
1226:                    return null;
1227:                }
1228:            }
1229:
1230:            /**
1231:             * Gets a Set of the extension(s) marked NON-CRITICAL in the
1232:             * certificate. In the returned set, each extension is
1233:             * represented by its OID string.
1234:             *   
1235:             * @return a set of the extension oid strings in the
1236:             * certificate that are NOT marked critical.
1237:             */
1238:            public Set getNonCriticalExtensionOIDs() {
1239:                if (info == null)
1240:                    return null;
1241:                try {
1242:                    CertificateExtensions exts = (CertificateExtensions) info
1243:                            .get(CertificateExtensions.NAME);
1244:                    if (exts == null)
1245:                        return null;
1246:
1247:                    HashSet extSet = new HashSet(11);
1248:                    Extension ex;
1249:                    for (Enumeration e = exts.getElements(); e
1250:                            .hasMoreElements();) {
1251:                        ex = (Extension) e.nextElement();
1252:                        if (!ex.isCritical())
1253:                            extSet.add(((ObjectIdentifier) ex.getExtensionId())
1254:                                    .toString());
1255:                    }
1256:                    return extSet;
1257:                } catch (Exception e) {
1258:                    return null;
1259:                }
1260:            }
1261:
1262:            /**
1263:             * Gets the extension identified by the given ObjectIdentifier
1264:             *
1265:             * @param oid the Object Identifier value for the extension.
1266:             * @return Extension or null if certificate does not contain this
1267:             *         extension
1268:             */
1269:            public Extension getExtension(ObjectIdentifier oid) {
1270:                if (info == null) {
1271:                    return null;
1272:                }
1273:                try {
1274:                    CertificateExtensions extensions = null;
1275:                    try {
1276:                        extensions = (CertificateExtensions) info
1277:                                .get(CertificateExtensions.NAME);
1278:                    } catch (CertificateException ce) {
1279:                        return null;
1280:                    }
1281:                    if (extensions == null) {
1282:                        return null;
1283:                    } else {
1284:                        Extension ex = null;
1285:                        for (Enumeration e = extensions.getElements(); e
1286:                                .hasMoreElements();) {
1287:                            ex = (Extension) e.nextElement();
1288:                            if (ex.getExtensionId().equals(oid))
1289:                                //NOTE: May want to consider cloning this
1290:                                return ex;
1291:                        }
1292:                        /* no such extension in this certificate */
1293:                        return null;
1294:                    }
1295:                } catch (IOException ioe) {
1296:                    return null;
1297:                }
1298:            }
1299:
1300:            /**
1301:             * Gets the DER encoded extension identified by the given
1302:             * oid String.
1303:             *
1304:             * @param oid the Object Identifier value for the extension.
1305:             */
1306:            public byte[] getExtensionValue(String oid) {
1307:                try {
1308:                    ObjectIdentifier findOID = new ObjectIdentifier(oid);
1309:                    String extAlias = OIDMap.getName(findOID);
1310:                    Extension certExt = null;
1311:
1312:                    if (extAlias == null) { // may be unknown
1313:                        // get the extensions, search thru' for this oid
1314:                        CertificateExtensions exts = (CertificateExtensions) info
1315:                                .get(CertificateExtensions.NAME);
1316:                        if (exts == null)
1317:                            return null;
1318:
1319:                        Extension ex = null;
1320:                        ;
1321:                        ObjectIdentifier inCertOID;
1322:                        for (Enumeration e = exts.getElements(); e
1323:                                .hasMoreElements();) {
1324:                            ex = (Extension) e.nextElement();
1325:                            inCertOID = ex.getExtensionId();
1326:                            if (inCertOID.equals(findOID)) {
1327:                                certExt = ex;
1328:                                break;
1329:                            }
1330:                        }
1331:                    } else { // there's sub-class that can handle this extension
1332:                        certExt = (Extension) this .get(extAlias);
1333:                    }
1334:                    if (certExt == null)
1335:                        return null;
1336:                    byte[] extData = certExt.getExtensionValue();
1337:                    if (extData == null)
1338:                        return null;
1339:
1340:                    DerOutputStream out = new DerOutputStream();
1341:                    out.putOctetString(extData);
1342:                    return out.toByteArray();
1343:                } catch (Exception e) {
1344:                    return null;
1345:                }
1346:            }
1347:
1348:            /**
1349:             * Get a boolean array representing the bits of the KeyUsage extension,
1350:             * (oid = 2.5.29.15).
1351:             * @return the bit values of this extension as an array of booleans.
1352:             */
1353:            public boolean[] getKeyUsage() {
1354:                try {
1355:                    String extAlias = OIDMap
1356:                            .getName(PKIXExtensions.KeyUsage_Id);
1357:                    if (extAlias == null)
1358:                        return null;
1359:
1360:                    KeyUsageExtension certExt = (KeyUsageExtension) this 
1361:                            .get(extAlias);
1362:                    if (certExt == null)
1363:                        return null;
1364:
1365:                    boolean[] ret = certExt.getBits();
1366:                    if (ret.length < NUM_STANDARD_KEY_USAGE) {
1367:                        boolean[] usageBits = new boolean[NUM_STANDARD_KEY_USAGE];
1368:                        System.arraycopy(ret, 0, usageBits, 0, ret.length);
1369:                        ret = usageBits;
1370:                    }
1371:                    return ret;
1372:                } catch (Exception e) {
1373:                    return null;
1374:                }
1375:            }
1376:
1377:            /**
1378:             * This method are the overridden implementation of
1379:             * getExtendedKeyUsage method in X509Certificate in the Sun
1380:             * provider. It is better performance-wise since it returns cached
1381:             * values.
1382:             */
1383:            public synchronized List getExtendedKeyUsage()
1384:                    throws CertificateParsingException {
1385:                if (readOnly && extKeyUsage != null) {
1386:                    return extKeyUsage;
1387:                } else {
1388:                    ExtendedKeyUsageExtension ext = getExtendedKeyUsageExtension();
1389:                    if (ext == null) {
1390:                        return null;
1391:                    }
1392:                    extKeyUsage = Collections.unmodifiableList(ext
1393:                            .getExtendedKeyUsage());
1394:                    return extKeyUsage;
1395:                }
1396:            }
1397:
1398:            /**
1399:             * This static method is the default implementation of the
1400:             * getExtendedKeyUsage method in X509Certificate. A
1401:             * X509Certificate provider generally should overwrite this to
1402:             * provide among other things caching for better performance.
1403:             */
1404:            public static List getExtendedKeyUsage(X509Certificate cert)
1405:                    throws CertificateParsingException {
1406:                try {
1407:                    byte[] ext = cert.getExtensionValue(EXTENDED_KEY_USAGE_OID);
1408:                    if (ext == null)
1409:                        return null;
1410:                    DerValue val = new DerValue(ext);
1411:                    byte[] data = val.getOctetString();
1412:
1413:                    ExtendedKeyUsageExtension ekuExt = new ExtendedKeyUsageExtension(
1414:                            Boolean.FALSE, data);
1415:                    return Collections.unmodifiableList(ekuExt
1416:                            .getExtendedKeyUsage());
1417:                } catch (IOException ioe) {
1418:                    CertificateParsingException cpe = new CertificateParsingException();
1419:                    cpe.initCause(ioe);
1420:                    throw cpe;
1421:                }
1422:            }
1423:
1424:            /**
1425:             * Get the certificate constraints path length from the
1426:             * the critical BasicConstraints extension, (oid = 2.5.29.19).
1427:             * @return the length of the constraint.
1428:             */
1429:            public int getBasicConstraints() {
1430:                try {
1431:                    String extAlias = OIDMap
1432:                            .getName(PKIXExtensions.BasicConstraints_Id);
1433:                    if (extAlias == null)
1434:                        return -1;
1435:                    BasicConstraintsExtension certExt = (BasicConstraintsExtension) this 
1436:                            .get(extAlias);
1437:                    if (certExt == null)
1438:                        return -1;
1439:
1440:                    if (((Boolean) certExt.get(BasicConstraintsExtension.IS_CA))
1441:                            .booleanValue() == true)
1442:                        return ((Integer) certExt
1443:                                .get(BasicConstraintsExtension.PATH_LEN))
1444:                                .intValue();
1445:                    else
1446:                        return -1;
1447:                } catch (Exception e) {
1448:                    return -1;
1449:                }
1450:            }
1451:
1452:            /**
1453:             * Converts a GeneralNames structure into an immutable Collection of 
1454:             * alternative names (subject or issuer) in the form required by 
1455:             * {@link #getSubjectAlternativeNames} or 
1456:             * {@link #getIssuerAlternativeNames}.
1457:             *
1458:             * @param names the GeneralNames to be converted
1459:             * @return an immutable Collection of alternative names
1460:             */
1461:            private static Collection makeAltNames(GeneralNames names) {
1462:                if (names.isEmpty())
1463:                    return Collections.EMPTY_SET;
1464:
1465:                HashSet newNames = new HashSet(names.size());
1466:                Iterator i = names.iterator();
1467:                while (i.hasNext()) {
1468:                    GeneralName gname = (GeneralName) i.next();
1469:                    GeneralNameInterface name = gname.getName();
1470:                    ArrayList nameEntry = new ArrayList(2);
1471:                    nameEntry.add(new Integer(name.getType()));
1472:                    switch (name.getType()) {
1473:                    case GeneralNameInterface.NAME_RFC822:
1474:                        nameEntry.add(((RFC822Name) name).getName());
1475:                        break;
1476:                    case GeneralNameInterface.NAME_DNS:
1477:                        nameEntry.add(((DNSName) name).getName());
1478:                        break;
1479:                    case GeneralNameInterface.NAME_DIRECTORY:
1480:                        nameEntry.add(((X500Name) name).getRFC2253Name());
1481:                        break;
1482:                    case GeneralNameInterface.NAME_URI:
1483:                        nameEntry.add(((URIName) name).getName());
1484:                        break;
1485:                    case GeneralNameInterface.NAME_IP:
1486:                        try {
1487:                            nameEntry.add(((IPAddressName) name).getName());
1488:                        } catch (IOException ioe) {
1489:                            // IPAddressName in cert is bogus
1490:                            throw new RuntimeException(
1491:                                    "IPAddress cannot be parsed", ioe);
1492:                        }
1493:                        break;
1494:                    case GeneralNameInterface.NAME_OID:
1495:                        nameEntry.add(((OIDName) name).getOID().toString());
1496:                        break;
1497:                    default:
1498:                        // add DER encoded form
1499:                        DerOutputStream derOut = new DerOutputStream();
1500:                        try {
1501:                            name.encode(derOut);
1502:                        } catch (IOException ioe) {
1503:                            // should not occur since name has already been decoded
1504:                            // from cert (this would indicate a bug in our code)
1505:                            throw new RuntimeException(
1506:                                    "name cannot be encoded", ioe);
1507:                        }
1508:                        nameEntry.add(derOut.toByteArray());
1509:                        break;
1510:                    }
1511:                    newNames.add(Collections.unmodifiableList(nameEntry));
1512:                }
1513:                return Collections.unmodifiableCollection(newNames);
1514:            }
1515:
1516:            /**
1517:             * Checks a Collection of altNames and clones any name entries of type 
1518:             * byte [].
1519:             */
1520:            private static Collection cloneAltNames(Collection altNames) {
1521:                boolean mustClone = false;
1522:                Iterator i = altNames.iterator();
1523:                while (i.hasNext() && !mustClone) {
1524:                    List nameEntry = (List) i.next();
1525:                    if (nameEntry.get(1) instanceof  byte[]) {
1526:                        // must clone names
1527:                        mustClone = true;
1528:                    }
1529:                }
1530:                if (mustClone) {
1531:                    HashSet namesCopy = new HashSet(altNames.size());
1532:                    i = altNames.iterator();
1533:                    while (i.hasNext()) {
1534:                        List nameEntry = (List) i.next();
1535:                        Object nameObject = nameEntry.get(1);
1536:                        if (nameObject instanceof  byte[]) {
1537:                            ArrayList nameEntryCopy = new ArrayList(
1538:                                    (List) nameEntry);
1539:                            nameEntryCopy.set(1, ((byte[]) nameObject).clone());
1540:                            namesCopy.add(Collections
1541:                                    .unmodifiableList(nameEntryCopy));
1542:                        } else
1543:                            namesCopy.add(nameEntry);
1544:                    }
1545:                    return Collections.unmodifiableCollection(namesCopy);
1546:                } else
1547:                    return altNames;
1548:            }
1549:
1550:            /**
1551:             * This method are the overridden implementation of
1552:             * getSubjectAlternativeNames method in X509Certificate in the Sun
1553:             * provider. It is better performance-wise since it returns cached
1554:             * values.
1555:             */
1556:            public synchronized Collection getSubjectAlternativeNames()
1557:                    throws CertificateParsingException {
1558:                // return cached value if we can
1559:                if (readOnly && subjectAlternativeNames != null)
1560:                    return cloneAltNames(subjectAlternativeNames);
1561:
1562:                SubjectAlternativeNameExtension subjectAltNameExt = getSubjectAlternativeNameExtension();
1563:                if (subjectAltNameExt == null)
1564:                    return null;
1565:
1566:                GeneralNames names;
1567:                try {
1568:                    names = (GeneralNames) subjectAltNameExt
1569:                            .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
1570:                } catch (IOException ioe) {
1571:                    // should not occur
1572:                    return Collections.EMPTY_SET;
1573:                }
1574:                subjectAlternativeNames = makeAltNames(names);
1575:                return subjectAlternativeNames;
1576:            }
1577:
1578:            /**
1579:             * This static method is the default implementation of the
1580:             * getSubjectAlternaitveNames method in X509Certificate. A
1581:             * X509Certificate provider generally should overwrite this to
1582:             * provide among other things caching for better performance.
1583:             */
1584:            public static Collection getSubjectAlternativeNames(
1585:                    X509Certificate cert) throws CertificateParsingException {
1586:                try {
1587:                    byte[] ext = cert.getExtensionValue(SUBJECT_ALT_NAME_OID);
1588:                    if (ext == null) {
1589:                        return null;
1590:                    }
1591:                    DerValue val = new DerValue(ext);
1592:                    byte[] data = val.getOctetString();
1593:
1594:                    SubjectAlternativeNameExtension subjectAltNameExt = new SubjectAlternativeNameExtension(
1595:                            Boolean.FALSE, data);
1596:
1597:                    GeneralNames names;
1598:                    try {
1599:                        names = (GeneralNames) subjectAltNameExt
1600:                                .get(SubjectAlternativeNameExtension.SUBJECT_NAME);
1601:                    } catch (IOException ioe) {
1602:                        // should not occur
1603:                        return Collections.EMPTY_SET;
1604:                    }
1605:                    return makeAltNames(names);
1606:                } catch (IOException ioe) {
1607:                    CertificateParsingException cpe = new CertificateParsingException();
1608:                    cpe.initCause(ioe);
1609:                    throw cpe;
1610:                }
1611:            }
1612:
1613:            /**
1614:             * This method are the overridden implementation of
1615:             * getIssuerAlternativeNames method in X509Certificate in the Sun
1616:             * provider. It is better performance-wise since it returns cached
1617:             * values.
1618:             */
1619:            public synchronized Collection getIssuerAlternativeNames()
1620:                    throws CertificateParsingException {
1621:                // return cached value if we can
1622:                if (readOnly && issuerAlternativeNames != null)
1623:                    return cloneAltNames(issuerAlternativeNames);
1624:
1625:                IssuerAlternativeNameExtension issuerAltNameExt = getIssuerAlternativeNameExtension();
1626:                if (issuerAltNameExt == null)
1627:                    return null;
1628:
1629:                GeneralNames names;
1630:                try {
1631:                    names = (GeneralNames) issuerAltNameExt
1632:                            .get(IssuerAlternativeNameExtension.ISSUER_NAME);
1633:                } catch (IOException ioe) {
1634:                    // should not occur
1635:                    return Collections.EMPTY_SET;
1636:                }
1637:                issuerAlternativeNames = makeAltNames(names);
1638:                return issuerAlternativeNames;
1639:            }
1640:
1641:            /**
1642:             * This static method is the default implementation of the
1643:             * getIssuerAlternaitveNames method in X509Certificate. A
1644:             * X509Certificate provider generally should overwrite this to
1645:             * provide among other things caching for better performance.
1646:             */
1647:            public static Collection getIssuerAlternativeNames(
1648:                    X509Certificate cert) throws CertificateParsingException {
1649:                try {
1650:                    byte[] ext = cert.getExtensionValue(ISSUER_ALT_NAME_OID);
1651:                    if (ext == null) {
1652:                        return null;
1653:                    }
1654:
1655:                    DerValue val = new DerValue(ext);
1656:                    byte[] data = val.getOctetString();
1657:
1658:                    IssuerAlternativeNameExtension issuerAltNameExt = new IssuerAlternativeNameExtension(
1659:                            Boolean.FALSE, data);
1660:                    GeneralNames names;
1661:                    try {
1662:                        names = (GeneralNames) issuerAltNameExt
1663:                                .get(IssuerAlternativeNameExtension.ISSUER_NAME);
1664:                    } catch (IOException ioe) {
1665:                        // should not occur
1666:                        return Collections.EMPTY_SET;
1667:                    }
1668:                    return makeAltNames(names);
1669:                } catch (IOException ioe) {
1670:                    CertificateParsingException cpe = new CertificateParsingException();
1671:                    cpe.initCause(ioe);
1672:                    throw cpe;
1673:                }
1674:            }
1675:
1676:            /************************************************************/
1677:
1678:            /*
1679:             * Cert is a SIGNED ASN.1 macro, a three elment sequence:
1680:             *
1681:             *	- Data to be signed (ToBeSigned) -- the "raw" cert
1682:             *	- Signature algorithm (SigAlgId)
1683:             *	- The signature bits
1684:             *
1685:             * This routine unmarshals the certificate, saving the signature
1686:             * parts away for later verification.
1687:             */
1688:            private void parse(DerValue val) throws CertificateException,
1689:                    IOException {
1690:                // check if can over write the certificate
1691:                if (readOnly)
1692:                    throw new CertificateParsingException(
1693:                            "cannot over-write existing certificate");
1694:
1695:                if (val.data == null)
1696:                    throw new CertificateParsingException(
1697:                            "invalid DER-encoded certificate data");
1698:
1699:                signedCert = val.toByteArray();
1700:                DerValue[] seq = new DerValue[3];
1701:
1702:                seq[0] = val.data.getDerValue();
1703:                seq[1] = val.data.getDerValue();
1704:                seq[2] = val.data.getDerValue();
1705:
1706:                if (val.data.available() != 0) {
1707:                    throw new CertificateParsingException(
1708:                            "signed overrun, bytes = " + val.data.available());
1709:                }
1710:                if (seq[0].tag != DerValue.tag_Sequence) {
1711:                    throw new CertificateParsingException(
1712:                            "signed fields invalid");
1713:                }
1714:
1715:                algId = AlgorithmId.parse(seq[1]);
1716:                signature = seq[2].getBitString();
1717:
1718:                if (seq[1].data.available() != 0) {
1719:                    throw new CertificateParsingException("algid field overrun");
1720:                }
1721:                if (seq[2].data.available() != 0)
1722:                    throw new CertificateParsingException(
1723:                            "signed fields overrun");
1724:
1725:                // The CertificateInfo
1726:                info = new X509CertInfo(seq[0]);
1727:
1728:                // the "inner" and "outer" signature algorithms must match
1729:                AlgorithmId infoSigAlg = (AlgorithmId) info
1730:                        .get(CertificateAlgorithmId.NAME + DOT
1731:                                + CertificateAlgorithmId.ALGORITHM);
1732:                if (!algId.equals(infoSigAlg))
1733:                    throw new CertificateException(
1734:                            "Signature algorithm mismatch");
1735:                readOnly = true;
1736:            }
1737:
1738:            /**
1739:             * Extract the subject or issuer X500Principal from an X509Certificate. 
1740:             * Parses the encoded form of the cert to preserve the principal's 
1741:             * ASN.1 encoding. 
1742:             */
1743:            private static X500Principal getX500Principal(X509Certificate cert,
1744:                    boolean getIssuer) throws Exception {
1745:                byte[] encoded = cert.getEncoded();
1746:                DerInputStream derIn = new DerInputStream(encoded);
1747:                DerValue tbsCert = derIn.getSequence(3)[0];
1748:                DerInputStream tbsIn = tbsCert.data;
1749:                DerValue tmp;
1750:                tmp = tbsIn.getDerValue();
1751:                // skip version number if present
1752:                if (tmp.isContextSpecific((byte) 0)) {
1753:                    tmp = tbsIn.getDerValue();
1754:                }
1755:                // tmp always contains serial number now
1756:                tmp = tbsIn.getDerValue(); // skip signature
1757:                tmp = tbsIn.getDerValue(); // issuer
1758:                if (getIssuer == false) {
1759:                    tmp = tbsIn.getDerValue(); // skip validity
1760:                    tmp = tbsIn.getDerValue(); // subject
1761:                }
1762:                byte[] principalBytes = tmp.toByteArray();
1763:                return new X500Principal(principalBytes);
1764:            }
1765:
1766:            /**
1767:             * Extract the subject X500Principal from an X509Certificate.
1768:             * Called from java.security.cert.X509Certificate.getSubjectX500Principal().
1769:             */
1770:            public static X500Principal getSubjectX500Principal(
1771:                    X509Certificate cert) {
1772:                try {
1773:                    return getX500Principal(cert, false);
1774:                } catch (Exception e) {
1775:                    throw new RuntimeException("Could not parse subject", e);
1776:                }
1777:            }
1778:
1779:            /**
1780:             * Extract the issuer X500Principal from an X509Certificate.
1781:             * Called from java.security.cert.X509Certificate.getIssuerX500Principal().
1782:             */
1783:            public static X500Principal getIssuerX500Principal(
1784:                    X509Certificate cert) {
1785:                try {
1786:                    return getX500Principal(cert, true);
1787:                } catch (Exception e) {
1788:                    throw new RuntimeException("Could not parse issuer", e);
1789:                }
1790:            }
1791:
1792:            /**
1793:             * Returned the encoding of the given certificate for internal use.
1794:             * Callers must guarantee that they neither modify it nor expose it 
1795:             * to untrusted code. Uses getEncodedInternal() if the certificate
1796:             * is instance of X509CertImpl, getEncoded() otherwise.
1797:             */
1798:            public static byte[] getEncodedInternal(Certificate cert)
1799:                    throws CertificateEncodingException {
1800:                if (cert instanceof  X509CertImpl) {
1801:                    return ((X509CertImpl) cert).getEncodedInternal();
1802:                } else {
1803:                    return cert.getEncoded();
1804:                }
1805:            }
1806:
1807:            /**
1808:             * Utility method to convert an arbitrary instance of X509Certificate
1809:             * to a X509CertImpl. Does a cast if possible, otherwise reparses
1810:             * the encoding.
1811:             */
1812:            public static X509CertImpl toImpl(X509Certificate cert)
1813:                    throws CertificateException {
1814:                if (cert instanceof  X509CertImpl) {
1815:                    return (X509CertImpl) cert;
1816:                } else {
1817:                    return X509Factory.intern(cert);
1818:                }
1819:            }
1820:
1821:            /**
1822:             * Utility method to test if a certificate is self-issued. This is
1823:             * the case iff the subject and issuer X500Principals are equal.
1824:             * New API subsetted out in CDC/FP and cannot be invoked here. It
1825:             * appears to be invoked only certpath code & exists in the
1826:             * security optional package version of this class.
1827:            public static boolean isSelfIssued(X509Certificate cert) {
1828:            X500Principal subject = cert.getSubjectX500Principal();
1829:            X500Principal issuer = cert.getIssuerX500Principal();
1830:            return subject.equals(issuer);
1831:            }
1832:             */
1833:
1834:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.