Source Code Cross Referenced for X509Certificate.java in  » Portal » Open-Portal » com » sun » portal » kssl » 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 » Portal » Open Portal » com.sun.portal.kssl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  @(#)X509Certificate.java	1.16 02/07/24 @(#)
0003:         *
0004:         * Copyright (c) 2000-2002 Sun Microsystems, Inc.  All rights reserved.
0005:         * PROPRIETARY/CONFIDENTIAL
0006:         * Use is subject to license terms.
0007:         */
0008:
0009:        package com.sun.portal.kssl;
0010:
0011:        import com.sun.portal.ksecurity.MessageDigest;
0012:        import com.sun.portal.ksecurity.RSAPublicKey;
0013:        import com.sun.portal.ksecurity.PublicKey;
0014:        import com.sun.portal.ksecurity.KeyBuilder;
0015:        import com.sun.portal.ksecurity.CryptoException;
0016:
0017:        import java.io.IOException;
0018:
0019:        import java.util.*;
0020:
0021:        import com.sun.portal.microedition.pki.*;
0022:
0023:        /**
0024:         * This class implements methods for creating X.509 certificates and
0025:         * accessing their attributes such as subject/issuer names, public keys
0026:         * and validity information. Publicly visible methods methods are 
0027:         * modeled after those in the X509Certificate classes 
0028:         * from J2SE (standard edition) but there are some differences and 
0029:         * these are documented below. <P />
0030:         * NOTE: For now, only X.509 certificates containing RSA public keys
0031:         * and signed either using md5WithRSA or sha-1WithRSA are supported.
0032:         * This version of the implementation is unable to parse certificates
0033:         * containing DSA keys or signed using DSA. Certificates containing
0034:         * RSA keys but signed using an unsupported algorithm (e.g. RSA_MD2)
0035:         * can be parsed but cannot be verified. Not all version 3 extensions are 
0036:         * supported (only subjectAltName, basicConstraints, keyUsage and
0037:         * extendedKeyUsage are recognized) but if an unrecognized
0038:         * extension is marked critical, an error notification is generated. 
0039:         * <P />
0040:         * @see com.sun.kssl.HandshakeListener
0041:         */
0042:        public class X509Certificate implements  Certificate {
0043:
0044:            /** Indicates a no error condition. */
0045:            public static final byte NO_ERROR = 0;
0046:
0047:            /**
0048:             * Indicates that no information is available on
0049:             * the pathLengthConstraint associated with this certificate
0050:             * (this could happen if the certifiate is a v1 or v2 cert or
0051:             * a v3 cert without basicConstraints or a non-CA v3 certificate).
0052:             */
0053:            public static final int MISSING_PATH_LENGTH_CONSTRAINT = -1;
0054:            /** Indicates there is no limit to the server certificate chain length. */
0055:            public static final int UNLIMITED_CERT_CHAIN_LENGTH = 65535;
0056:
0057:            /** We expect issuer/subject names to fit within these many bytes. */
0058:            private static final int MAX_NAME_LENGTH = 300;
0059:
0060:            /** ASN ANY_STRING type used in certificate parsing (0x00). */
0061:            private static final byte ANY_STRING_TYPE = 0x00; // our own hack
0062:            // private static final byte BOOLEAN_TYPE  = 0x01 ?????
0063:            /** ASN INTEGER type used in certificate parsing (0x02). */
0064:            private static final byte INTEGER_TYPE = 0x02;
0065:            /** ASN BIT STRING type used in certificate parsing (0x03). */
0066:            private static final byte BITSTRING_TYPE = 0x03;
0067:            /** ASN OCTET STRING type used in certificate parsing (0x04). */
0068:            private static final byte OCTETSTR_TYPE = 0x04;
0069:            /** ASN OBJECT ID type used in certificate parsing (0x06). */
0070:            private static final byte OID_TYPE = 0x06;
0071:            /** ASN UTF8 STRING type used in certificate parsing (0x0c). */
0072:            private static final byte UTF8STR_TYPE = 0x0c;
0073:            /** ASN UNICODE STRING type used in certificate parsing (0x12). */
0074:            private static final byte UNIVSTR_TYPE = 0x12;
0075:            /** ASN PRINT STRING type used in certificate parsing (0x13). */
0076:            private static final byte PRINTSTR_TYPE = 0x13;
0077:            /** ASN TELETEX STRING type used in certificate parsing (0x14). */
0078:            private static final byte TELETEXSTR_TYPE = 0x14;
0079:            // private static final byte BMPSTR_TYPE     = 0x??
0080:            /** ASN IA5 STRING type used in certificate parsing (0x16). */
0081:            private static final byte IA5STR_TYPE = 0x16; // Used for EmailAddress
0082:            /** ASN SEQUENCE type used in certificate parsing (0x30). */
0083:            private static final byte SEQUENCE_TYPE = 0x30;
0084:            /** ASN SET type used in certificate parsing (0x31). */
0085:            private static final byte SET_TYPE = 0x31;
0086:
0087:            /** Email address (rfc 822) alternative name type code. */
0088:            public static final byte TYPE_EMAIL_ADDRESS = 1;
0089:            /** DNS name alternative name type code. */
0090:            public static final byte TYPE_DNS_NAME = 2;
0091:            /** URI alternative name type code. */
0092:            public static final byte TYPE_URI = 6;
0093:
0094:            /**
0095:             * The validity period is contained in thirteen bytes
0096:             * yymmddhhmmss followed by 'Z' (for zulu ie GMT), if yy < 50
0097:             * assume 20yy else 19yy.
0098:             */
0099:            private static final int UTC_LENGTH = 13;
0100:
0101:            /**
0102:             * Maps byte codes that follow id-at (0x55 0x04) to corresponding name
0103:             * component tags (e.g. Commom Name, or CN, is 0x55, 0x04, 0x03 and
0104:             * Country, or C, is 0x55, 0x04, 0x06). See getName. See X.520 for
0105:             * the OIDs and RFC 1779 for the printable labels. Place holders for
0106:             * unknown labels have a 0 as the first char.
0107:             */
0108:            private static final char[][] nameAttr = { { 0 }, { 0 }, { 0 },
0109:                    { 'C', 'N' }, // Common name: id-at 3
0110:                    { 'S', 'N' }, // Surname: id-at 4
0111:                    { 0 }, { 'C' }, // Country: id-at 6
0112:                    { 'L' }, // Locality: id-at 7
0113:                    { 'S', 'T' }, // State or province: id-at 8
0114:                    { 'S', 'T', 'R', 'E', 'E', 'T' }, // Street address: id-at 9
0115:                    { 'O' }, // Organization: id-at 10
0116:                    { 'O', 'U' }, // Organization unit: id-at 11
0117:            };
0118:
0119:            /** Email attribute label in bytes. "EmailAddress" */
0120:            private static final char[] EMAIL_ATTR_LABEL = { 'E', 'm', 'a',
0121:                    'i', 'l', 'A', 'd', 'd', 'r', 'e', 's', 's' };
0122:
0123:            /** Email attribute object identifier. */
0124:            private static final byte[] EMAIL_ATTR_OID = { (byte) 0x2a,
0125:                    (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7,
0126:                    (byte) 0x0d, (byte) 0x01, (byte) 0x09, (byte) 0x01 };
0127:
0128:            /** Includes DER encoding for OID 1.2.840.113549.1.1. */
0129:            /*private static final byte[] PKCS1Seq = {
0130:                (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, 
0131:                (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
0132:                (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
0133:            };*/
0134:            private static final byte[] PKCS1Seq = { (byte) 0x06, (byte) 0x09,
0135:                    (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
0136:                    (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, };
0137:
0138:            /*
0139:             * These signature algorithms are encoded as PKCS1Seq followed by
0140:             * a single byte with the corresponding value shown below, e.g.
0141:             * md5WithRSAEncryption OBJECT IDENTIFIER  ::=  { 
0142:             *     iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
0143:             *     pkcs-1(1) 4  
0144:             * }
0145:             */
0146:            /** Uknown algorithm (-1). */
0147:            private static final byte NONE = -1;
0148:            /** RAS ENCRYPTION (0x01). */
0149:            private static final byte RSA_ENCRYPTION = 0x01;
0150:            /** MD2_RSA algorithm (0x02). */
0151:            private static final byte MD2_RSA = 0x02;
0152:            /** MD4_RSA algorithm (0x03). */
0153:            private static final byte MD4_RSA = 0x03;
0154:            /** MD4_RSA algorithm (0x04). */
0155:            private static final byte MD5_RSA = 0x04;
0156:            /** SHA1_RSA algorithm (0x05). */
0157:            private static final byte SHA1_RSA = 0x05;
0158:
0159:            /**
0160:             * Expected prefix in decrypted value when MD2 hash is used for signing
0161:             *  30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 see verify().
0162:             */
0163:            private static final byte[] PREFIX_MD2 = { (byte) 0x30,
0164:                    (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
0165:                    (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
0166:                    (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x02,
0167:                    (byte) 0x02, (byte) 0x05, (byte) 0x00, (byte) 0x04,
0168:                    (byte) 0x10 };
0169:
0170:            /**
0171:             * Expected prefix in decrypted value when MD5 hash is used for signing
0172:             *  30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 see verify().
0173:             */
0174:            private static final byte[] PREFIX_MD5 = { (byte) 0x30,
0175:                    (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
0176:                    (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
0177:                    (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x02,
0178:                    (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x04,
0179:                    (byte) 0x10 };
0180:            /**
0181:             * Expected prefix in decrypted value when SHA-1 hash is used for signing
0182:             * 30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14.
0183:             */
0184:            private static final byte[] PREFIX_SHA1 = { (byte) 0x30,
0185:                    (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06,
0186:                    (byte) 0x05, (byte) 0x2b, (byte) 0x0e, (byte) 0x03,
0187:                    (byte) 0x02, (byte) 0x1a, (byte) 0x05, (byte) 0x00,
0188:                    (byte) 0x04, (byte) 0x14 };
0189:
0190:            /** ASN encoding for NULL. */
0191:            private static final byte[] NullSeq = { (byte) 0x05, (byte) 0x00 };
0192:
0193:            /** This is how the encoding of validity information begins. */
0194:            private static final byte[] ValiditySeq = { (byte) 0x30,
0195:                    (byte) 0x1e };
0196:
0197:            /** This is how the encoding of UTCTime begins. */
0198:            private static final byte[] UTCSeq = { (byte) 0x17, (byte) 0x0d };
0199:
0200:            /** Includes DER encoding for id-kp (key purpose). */
0201:            private static final byte[] ID_KP = { (byte) 0x2b, (byte) 0x06,
0202:                    (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x07,
0203:                    (byte) 0x03 };
0204:
0205:            /** True iff subject matches issuer. */
0206:            private boolean selfSigned;
0207:            /** X.509 version. For more readable code the version field starts a 1. */
0208:            private byte version = 1;
0209:            /** MD5 fingerprint of the certificate. */
0210:            private byte[] fp = null;
0211:            /** Certificate serial number. */
0212:            private String serialNumber;
0213:            /** Certificate subject. */
0214:            private String subject;
0215:            /** Certificate issuer. */
0216:            private String issuer;
0217:            /** Beginning of certificate validity period. */
0218:            private long from = 0;
0219:            /** End of certificate validity period. */
0220:            private long until = 0;
0221:            /** Certificate RSA Public key. */
0222:            private RSAPublicKey pubKey = null;
0223:
0224:            // The following fields are only meaningful in certificates created
0225:            // by fully parsing the DER encoding. They are meaningless on
0226:            // certificates created using the Certificate constructor below.
0227:            /** Index inside encoding. */
0228:            private int idx = 0;
0229:            /** Contains Certificate DER encoding. */
0230:            private byte[] enc = null;
0231:            /** Offset where TBSCertificate starts. */
0232:            private int TBSStart = 0;
0233:            /** Length of TBSCertificate. */
0234:            private int TBSLen = 0;
0235:            /** Algorithm used to sign the cert. */
0236:            private byte sigAlg = NONE;
0237:            /** Issuer signature on certificate. */
0238:            private byte[] signature = null;
0239:            /**  Hash of TBSCertificate. */
0240:            private byte[] TBSCertHash = null;
0241:            /**  True iff cert has unrecognized critical extension. */
0242:            private boolean badExt = false;
0243:            /**  Alternate name. */
0244:
0245:            /** format of the subject alternative name, 2 means a DNS name */
0246:            private byte subAltNameType;
0247:            /** subject alternative name */
0248:            private Object subAltName;
0249:            /** does the cert include BasicConstaints. */
0250:            private boolean hasBC = false;
0251:            /** CA value in BasicConstraints. */
0252:            private boolean isCA = false;
0253:            /** Path Length constriant from Basic constraints. */
0254:            private int pLenConstr = MISSING_PATH_LENGTH_CONSTRAINT;
0255:            /** Collection of keyUsage bits. */
0256:            private long keyUsage = -1;
0257:
0258:            /** Private constructor */
0259:            private X509Certificate() {
0260:            }
0261:
0262:            /**
0263:             * Creates an X.509 certificate with the specified attributes.
0264:             * This constructor is only used for creating trusted certificates. 
0265:             * <BR />
0266:             * <B>NOTE:</B> All signature related values in these certificates 
0267:             * (such as the signing algorithm and signature) are set to null and
0268:             * invoking methods that access signature information, e.g. verify()
0269:             * and getSigAlgName() can produce unexpected errors.
0270:             * <P />
0271:             * @param ver        byte containing X.509 version
0272:             * @param rawSerialNumber byte array containing the serial number
0273:             * @param sub        subject name
0274:             * @param iss        issuer name
0275:             * @param notBefore  start of validity period expressed in milliseconds
0276:             *                   since midnight Jan 1, 1970 UTC 
0277:             * @param notAfter   end of validity period expressed as above
0278:             * @param mod        modulus associated with the RSA Public Key
0279:             * @param exp        exponent associated with the RSA Public Key
0280:             * @param chash      16-byte MD5 hash of the certificate's ASN.1 
0281:             *                   DER encoding
0282:             * @param pLen       Is the pathLenConstraint associated with a version 3
0283:             *                   certificate. This parameter is ignored for v1 and
0284:             *                   v2 certificates. If a v3 certificate does not
0285:             *                   have basicConstraints or is not a CA cert, callers
0286:             *                   should pass MISSING_PATH_LENGTH_CONSTRAINT. If the
0287:             *                   v3 certificate has basicConstraints, CA is set but
0288:             *                   pathLenConstraint is missing (indicating no limit
0289:             *                   on the certificate chain), callers should pass
0290:             *                   UNLIMITED_CERT_CHAIN_LENGTH.
0291:             * @exception Exception in case of a problem with RSA public key parameters
0292:             */
0293:            public X509Certificate(byte ver, byte[] rawSerialNumber,
0294:                    String sub, String iss, long notBefore, long notAfter,
0295:                    byte[] mod, byte[] exp, byte[] chash, int pLen)
0296:                    throws Exception {
0297:                version = ver;
0298:                serialNumber = Utils.hexEncode(rawSerialNumber, 0,
0299:                        rawSerialNumber.length);
0300:
0301:                /*
0302:                 * We are paranoid so we don't just assign a reference as in
0303:                 * fp = chash; subject = sub; issuer = iss;
0304:                 */
0305:                if (chash != null) {
0306:                    fp = new byte[chash.length];
0307:                    System.arraycopy(chash, 0, fp, 0, chash.length);
0308:                }
0309:
0310:                subject = new String(sub);
0311:                issuer = new String(iss);
0312:                from = notBefore;
0313:                until = notAfter;
0314:                sigAlg = NONE;
0315:
0316:                if (subject.compareTo(issuer) == 0) {
0317:                    selfSigned = true;
0318:                }
0319:
0320:                pubKey = (RSAPublicKey) KeyBuilder.buildKey(
0321:                        KeyBuilder.TYPE_RSA_PUBLIC, (short) (mod.length << 3),
0322:                        false);
0323:                pubKey.setModulus(mod, (short) 0, (short) mod.length);
0324:                pubKey.setExponent(exp, (short) 0, (short) exp.length);
0325:
0326:                if ((ver == 3) && (pLen != MISSING_PATH_LENGTH_CONSTRAINT)) {
0327:                    hasBC = isCA = true;
0328:                    pLenConstr = pLen;
0329:                }
0330:            }
0331:
0332:            /**
0333:             * Matches the contents of buf against this certificates DER
0334:             * encoding (enc) starting at the current offset (idx).
0335:             * <P />
0336:             * @param buf buffer whose contents are to be matched against the
0337:             *            certificate encoding
0338:             * @exception Exception if the match fails
0339:             */
0340:            private void match(byte[] buf) throws Exception {
0341:                if (idx + buf.length < enc.length) {
0342:                    for (int i = 0; i < buf.length; i++) {
0343:                        if (enc[idx++] != buf[i])
0344:                            throw new Exception("match() error 1");
0345:                    }
0346:                } else {
0347:                    throw new Exception("match() error 2");
0348:                }
0349:            }
0350:
0351:            /**
0352:             * Matches the specified ASN type against this certificates DER
0353:             * encoding (enc) starting at the current offset (idx) and returns
0354:             * its encoded length.
0355:             * <P />
0356:             * @param type ASN type to be matched
0357:             * @return the size in bytes of the sub-encoding associated with
0358:             *         the given type
0359:             * @exception IOException if the length is not formated correctly
0360:             */
0361:            private int getLen(byte type) throws IOException {
0362:                // System.out.println("Matching " + type + " against " + enc[idx]);
0363:                if ((enc[idx] == type) || ((type == ANY_STRING_TYPE) && // ordered by likelihood of match
0364:                        ((enc[idx] == PRINTSTR_TYPE)
0365:                                || (enc[idx] == TELETEXSTR_TYPE)
0366:                                || (enc[idx] == UTF8STR_TYPE)
0367:                                || (enc[idx] == IA5STR_TYPE) || (enc[idx] == UNIVSTR_TYPE)))) {
0368:                    idx++;
0369:                    int size = (enc[idx++] & 0xff);
0370:                    if (size >= 128) {
0371:                        int tmp = size - 128;
0372:                        // NOTE: for now, all sizes must fit int two bytes
0373:                        if ((tmp > 2) || (idx + tmp > enc.length)) {
0374:                            throw new IOException("getLen() err 1");
0375:                        } else {
0376:                            size = 0;
0377:                            while (tmp > 0) {
0378:                                size = (size << 8) + (enc[idx++] & 0xff);
0379:                                tmp--;
0380:                            }
0381:                        }
0382:                    }
0383:                    // System.out.println(" ... size is " + size);
0384:                    return size;
0385:                }
0386:
0387:                throw new IOException("getLen() err 2");
0388:            }
0389:
0390:            /**
0391:             * Expects to see a PKCS1 algorithm identifier in the DER encoding
0392:             * (enc) starting at the current offset (idx). 
0393:             * <P />
0394:             * @return a single-byte algorithm identifier, e.g. MD5_RSA, MD2_RSA
0395:             * @exception Exception if an error is encountered during parsing
0396:             */
0397:            /*
0398:             * Patch added to support algorithm encoding without null
0399:             * sequence.
0400:             */
0401:            /*private byte getAlg() throws IOException {
0402:                byte val;
0403:                
0404:                try {
0405:                    match(PKCS1Seq);
0406:                    val = enc[idx++];
0407:                    match(NullSeq);
0408:                    return val;
0409:                } catch (Exception e) {
0410:                    throw new IOException("Algorithm Id parsing failed");
0411:                }
0412:            }*/
0413:            private byte getAlg() throws IOException {
0414:                byte val;
0415:                int len;
0416:
0417:                if (enc[idx++] != SEQUENCE_TYPE)
0418:                    throw new IOException("Algorithm Id parsing failed");
0419:                try {
0420:                    len = (enc[idx++] & 0xff);
0421:                    match(PKCS1Seq);
0422:                    val = enc[idx++];
0423:                    /* Check for optional null sequence */
0424:                    if (len > PKCS1Seq.length + 1)
0425:                        match(NullSeq);
0426:                    return val;
0427:                } catch (Exception e) {
0428:                    throw new IOException("Algorithm Id parsing failed");
0429:                }
0430:            }
0431:
0432:            /**
0433:             * Parses a SubjectName or IssuerName in the DER encoding
0434:             * (enc) starting at the current offset (idx) and ending
0435:             * at end. 
0436:             * <P />
0437:             * @param end ending offset for the DER-encoded name
0438:             * @return a human friendly string representation of the name
0439:             * @exception IOException if an error is encountered during parsing
0440:             */
0441:            private String getName(int end) throws IOException {
0442:                byte[] name = new byte[MAX_NAME_LENGTH];
0443:                int nameLen = 0;
0444:                int len = 0;
0445:                int cidx; // index where the most recently seen name component starts
0446:                int clen; // Component length
0447:                char[] label = null;
0448:                int aidx;
0449:
0450:                while (idx < end) {
0451:                    if (nameLen != 0) {
0452:                        // this is not the first time so insert a separator
0453:                        name[nameLen++] = (byte) ';';
0454:                    }
0455:
0456:                    getLen(SET_TYPE);
0457:                    getLen(SEQUENCE_TYPE);
0458:
0459:                    /*
0460:                     * Save the start of name component, e.g CommonName
0461:                     * ... and its length
0462:                     */
0463:                    clen = getLen(OID_TYPE);
0464:                    cidx = idx;
0465:                    idx += clen;
0466:
0467:                    /*
0468:                     * At this point we tag the name component, e.g. C= or hex
0469:                     * if unknown.
0470:                     */
0471:                    if ((clen == 3) && (enc[cidx] == 0x55)
0472:                            && (enc[cidx + 1] == 0x04)) {
0473:                        // begins with id-at, so try to see if we have a label
0474:                        aidx = enc[cidx + 2] & 0xFF;
0475:                        if ((aidx < nameAttr.length)
0476:                                && (nameAttr[aidx][0] != 0)) {
0477:                            label = nameAttr[aidx];
0478:                        } else {
0479:                            label = Utils.hexEncodeToChars(enc, cidx, clen);
0480:                        }
0481:                    } else if (Utils.byteMatch(enc, cidx, EMAIL_ATTR_OID, 0,
0482:                            EMAIL_ATTR_OID.length)) {
0483:                        label = EMAIL_ATTR_LABEL;
0484:                    } else {
0485:                        label = Utils.hexEncodeToChars(enc, cidx, clen);
0486:                    }
0487:
0488:                    for (int i = 0; i < label.length; i++) {
0489:                        name[nameLen++] = (byte) label[i];
0490:                    }
0491:
0492:                    name[nameLen++] = (byte) '=';
0493:
0494:                    len = getLen(ANY_STRING_TYPE);
0495:
0496:                    if (len > 0) {
0497:                        for (int i = 0; i < len; i++) {
0498:                            name[nameLen++] = enc[idx++];
0499:                        }
0500:                    }
0501:                }
0502:                return new String(name, 0, nameLen);//, "UTF-8");
0503:            }
0504:
0505:            /**
0506:             * Gets a string representation of the UTC time whose DER ecnoding
0507:             * is contained in the specified buffer.
0508:             * <P />
0509:             * @param buf buffer containing the DER encoding of UTC Time
0510:             * @param off starting offset of the encoding inside buf
0511:             * @return a string represntation of the UTC time in the form
0512:             * yy/mm/dd hh:mm:ss
0513:             * @exception IOException if an error is encountered during parsing
0514:             */
0515:            private static long getUTCTime(byte[] buf, int off)
0516:                    throws IOException {
0517:                int[] period = new int[6]; // year, month, day, hour, minute, second
0518:                if (buf[off + UTC_LENGTH - 1] != (byte) 'Z')
0519:                    throw new IOException("getUTCTime() err 1");
0520:                for (int i = 0; i < 6; i++) {
0521:                    period[i] = 0;
0522:                    if ((buf[2 * i + off] < (byte) '0')
0523:                            || (buf[2 * i + off] > (byte) '9'))
0524:                        throw new IOException("getUTCTime() err 2");
0525:                    period[i] = buf[2 * i + off] - (int) '0';
0526:                    if ((buf[2 * i + off + 1] < (byte) '0')
0527:                            || (buf[2 * i + off + 1] > (byte) '9'))
0528:                        throw new IOException("getUTCTime() err 3");
0529:                    period[i] = (period[i] * 10)
0530:                            + (buf[2 * i + off + 1] - (int) '0');
0531:                }
0532:
0533:                if (period[0] < 50) { // from rfc2459
0534:                    period[0] += 2000;
0535:                } else {
0536:                    period[0] += 1900;
0537:                }
0538:
0539:                Calendar cal = Calendar.getInstance();
0540:                cal.set(Calendar.YEAR, period[0]);
0541:                cal.set(Calendar.MONTH, period[1] - 1); // months go 0-11
0542:                cal.set(Calendar.DAY_OF_MONTH, period[2]);
0543:                cal.set(Calendar.HOUR_OF_DAY, period[3]);
0544:                cal.set(Calendar.MINUTE, period[4]);
0545:                cal.set(Calendar.SECOND, period[5]);
0546:                long res = cal.getTime().getTime();
0547:                return (res);
0548:            }
0549:
0550:            /**
0551:             * Parses X.509v3 extensions in the certificate encoding until
0552:             * the specified index.
0553:             * <p />
0554:             * @param end index of the last byte in the certificate encoding
0555:             *        to be processed
0556:             * @exception IOException in case of parsing problems
0557:             */
0558:            private void parseExtensions(int end) throws IOException {
0559:                /*
0560:                 * NOTE: If one does not wish to support v3 extensions
0561:                 * at all (to save code), one can simply set badExt to
0562:                 * true and return -- the code that actually parses extensions
0563:                 * can be commented out
0564:                 */
0565:                String extId = null;
0566:                int extIdIdx = 0;
0567:                int extIdLen = 0;
0568:                boolean crit;
0569:                int extValIdx = 0;
0570:                int extValLen = 0;
0571:                int tmp;
0572:
0573:                getLen((byte) 0xa3); // extensions start with 0xa3
0574:                getLen(SEQUENCE_TYPE);
0575:                while (idx < end) {
0576:                    extId = null;
0577:                    getLen(SEQUENCE_TYPE);
0578:                    extIdLen = getLen(OID_TYPE);
0579:                    extIdIdx = idx;
0580:                    idx += extIdLen;
0581:                    crit = false;
0582:                    if ((enc[idx] == 0x01) && (enc[idx + 1] == 0x01)) {
0583:                        idx += 2;
0584:                        crit = (enc[idx++] == (byte) 0xff) ? true : false;
0585:                    }
0586:                    extValLen = getLen(OCTETSTR_TYPE);
0587:                    extValIdx = idx;
0588:                    if ((enc[extIdIdx] == 0x55) && (enc[extIdIdx + 1] == 0x1d)) {
0589:                        // Do we recognize this? NOTE: id-ce is 0x55, 0x1d
0590:                        switch (enc[extIdIdx + 2] & 0xff) {
0591:                        case 0x0f: // keyUsage = id-ce 15
0592:                            extId = "KU";
0593:                            if (keyUsage == -1) {
0594:                                keyUsage = 0L;
0595:                            }
0596:
0597:                            tmp = getLen(BITSTRING_TYPE) - 1;
0598:                            int unused = enc[idx++]; // get unused bits in last octet
0599:                            byte b = 0;
0600:
0601:                            // process each bit in the bitstring starting with
0602:                            // the most significant
0603:                            for (int i = 0; i < ((tmp << 3) - unused); i++) {
0604:                                if ((i % 8) == 0) {
0605:                                    b = enc[idx++];
0606:                                }
0607:
0608:                                if (b < 0) {
0609:                                    keyUsage |= 1 << i;
0610:                                }
0611:
0612:                                b = (byte) (b << 1);
0613:                            }
0614:
0615:                            break;
0616:
0617:                        case 0x11: // subAltName = id-ce 17
0618:                            StringBuffer temp = new StringBuffer();
0619:                            int start = idx + 4;
0620:                            int length = extValLen - 4;
0621:                            extId = "SAN";
0622:
0623:                            /*
0624:                             * First byte stores the type e.g. 1=rfc822Name(email), 
0625:                             * 2=dNSName, 6=URI etc
0626:                             */
0627:                            subAltNameType = (byte) (enc[idx + 2] - 0x80);
0628:
0629:                            switch (subAltNameType) {
0630:                            case TYPE_EMAIL_ADDRESS:
0631:                            case TYPE_DNS_NAME:
0632:                            case TYPE_URI:
0633:                                for (int i = 0; i < length; i++) {
0634:                                    temp.append((char) enc[start + i]);
0635:                                }
0636:
0637:                                subAltName = temp.toString();
0638:                                break;
0639:
0640:                            default:
0641:                                subAltName = new byte[length];
0642:                                for (int i = 0; i < length; i++) {
0643:                                    ((byte[]) subAltName)[i] = enc[start + i];
0644:                                }
0645:                            }
0646:
0647:                            break;
0648:
0649:                        case 0x13: // basicConstr = id-ce 19
0650:                            hasBC = true;
0651:                            extId = "BC";
0652:                            tmp = getLen(SEQUENCE_TYPE);
0653:                            if (tmp == 0)
0654:                                break;
0655:                            // ca is encoded as an ASN boolean (default is false)
0656:                            if ((enc[idx] == 0x01) && (enc[idx + 1] == 0x01)
0657:                                    && (enc[idx + 2] == (byte) 0xff)) {
0658:                                isCA = true;
0659:                                idx += 3;
0660:                            }
0661:
0662:                            /*
0663:                             * path length constraint is encoded as optional ASN
0664:                             * integer
0665:                             */
0666:                            if ((enc[idx] == 0x02) && (enc[idx + 1] != 0)) {
0667:                                tmp = getLen(INTEGER_TYPE);
0668:                                pLenConstr = 0;
0669:                                for (int i = 0; i < tmp; i++) {
0670:                                    pLenConstr = (pLenConstr << 16)
0671:                                            + enc[idx + i];
0672:                                }
0673:                                idx += tmp;
0674:                            } else {
0675:                                if (isCA)
0676:                                    pLenConstr = UNLIMITED_CERT_CHAIN_LENGTH;
0677:                            }
0678:                            break;
0679:
0680:                        case 0x25: // extendedKeyUsage = id-ce 37
0681:                            long tempUsage = keyUsage;
0682:
0683:                            extId = "EKU";
0684:                            if (keyUsage == -1) {
0685:                                keyUsage = 0L;
0686:                            }
0687:
0688:                            getLen(SEQUENCE_TYPE);
0689:                            int kuOidLen;
0690:                            while (idx < extValIdx + extValLen) {
0691:                                kuOidLen = getLen(OID_TYPE);
0692:                                if ((kuOidLen == ID_KP.length + 1)
0693:                                        && Utils.byteMatch(enc, idx, ID_KP, 0,
0694:                                                ID_KP.length)
0695:                                        && (enc[idx + ID_KP.length] > 0)
0696:                                        && (enc[idx + ID_KP.length] < 9)) {
0697:                                    keyUsage |= (1 << (16 + enc[idx
0698:                                            + ID_KP.length]));
0699:                                } else {
0700:                                    if (crit)
0701:                                        badExt = true;
0702:                                }
0703:                                idx += kuOidLen;
0704:                            }
0705:
0706:                            if (!crit) {
0707:                                // ignore extended key usage if not critical
0708:                                keyUsage = tempUsage;
0709:                            }
0710:
0711:                            break;
0712:                        /* 
0713:                         * Extensions which we do not currently support include: 
0714:                         * subjectDirectoryAttribute 0x09, 
0715:                         * subjectKeyIdentifier 0x0e, privateKeyUsagePeriod 0x10,
0716:                         * issuerAltName 0x12, cRLNumber 0x14, reasonCode 0x15,
0717:                         * instructionCode 0x17, invalidityDate 0x18,
0718:                         * deltaCRLIndicator 0x1b, issuingDistributionPoint 0x1c,
0719:                         * certificateIssuer 0x1d, nameConstraints 0x1e,
0720:                         * cRLDistributionPoints 0x1f, certificatePolicies 0x20,
0721:                         * policyMappings 0x21, authorityKeyIdentifier 0x23,
0722:                         * policyConstraints 0x24
0723:                         */
0724:                        }
0725:                    }
0726:
0727:                    /* 
0728:                    // For debugging only
0729:                    System.out.println("<Id: " + 
0730:                                       Utils.hexEncode(enc, extIdIdx, extIdLen) +
0731:                                       (crit ? ", critical, " : ", ") +
0732:                                       Utils.hexEncode(enc, extValIdx, extValLen) +
0733:                                       ">" + 
0734:                                       ((extId == null) ? " (Unrecognized)" : ""));
0735:                     */
0736:
0737:                    if ((extId == null) && crit)
0738:                        badExt = true;
0739:
0740:                    idx = extValIdx + extValLen;
0741:                }
0742:
0743:                if (idx != end) {
0744:                    throw new IOException("Extension parsing problem");
0745:                }
0746:
0747:            } // Done processing extensions
0748:
0749:            /**
0750:             * Creates a certificate by parsing the ASN.1 DER X.509 certificate
0751:             * encoding in the specified buffer.<BR />
0752:             * <B>NOTE:</B> In the standard edition, equivalent functionality
0753:             * is provided by CertificateFactory.generateCertificate(InputStream).
0754:             * <P />
0755:             * @param buf byte array to be read
0756:             * @param off offset within the byte array
0757:             * @param len number of bytes to be read
0758:             * @return a certificate object corresponding to the DER encoding
0759:             *         or null (in case of an encoding problem)
0760:             * @exception IOException if there is a parsing error
0761:             */
0762:            public static X509Certificate generateCertificate(byte[] buf,
0763:                    int off, int len) throws IOException {
0764:
0765:                /*
0766:                 * force bad parameter errors now, so later we can consider any out of
0767:                 * bounds errors to be parsing errors
0768:                 */
0769:                int test = buf[off] + buf[len - 1] + buf[off + len - 1];
0770:
0771:                // long t1 = System.currentTimeMillis();
0772:
0773:                try {
0774:                    int start = 0;
0775:                    int size = 0;
0776:                    byte[] hash = new byte[16]; // for MD5 fingerprint
0777:                    X509Certificate res = null;
0778:                    int publicKeyLen;
0779:                    int publicKeyPos;
0780:
0781:                    // Compute the MD5 fingerprint
0782:                    MessageDigest md = MessageDigest.getInstance(
0783:                            MessageDigest.ALG_MD5, false);
0784:                    md.doFinal(buf, off, len, hash, 0);
0785:
0786:                    /*
0787:                     * Create a new certificate and fill its attributes by parsing 
0788:                     * the DER encoding
0789:                     */
0790:                    res = new X509Certificate();
0791:                    // Prepare to parse this certificate
0792:                    res.idx = 0;
0793:                    // Set the encoding
0794:                    res.enc = new byte[len];
0795:                    System.arraycopy(buf, off, res.enc, 0, len);
0796:                    // ... and the fingerprint
0797:                    res.fp = new byte[hash.length];
0798:                    System.arraycopy(hash, 0, res.fp, 0, hash.length);
0799:
0800:                    // System.out.println("-------- Begin Certificate -------");
0801:                    // Utils.hexEncode(buf, off, len);
0802:
0803:                    /*
0804:                     * A Certificate is a sequence of a TBSCertificate, a signature
0805:                     * algorithm identifier and the signature
0806:                     */
0807:                    res.getLen(SEQUENCE_TYPE);
0808:                    // Now read the TBS certificate
0809:                    res.TBSStart = res.idx;
0810:                    size = res.getLen(SEQUENCE_TYPE);
0811:                    // System.out.println("------- Begin TBSCertificate -------\n" +
0812:                    // Utils.hexEncode(res.enc, res.idx, size));
0813:                    int sigAlgIdx = res.idx + size;
0814:                    res.TBSLen = sigAlgIdx - res.TBSStart;
0815:                    // Now parse the version
0816:                    if ((res.enc[res.idx] & 0xf0) == 0xa0) {
0817:                        res.idx++;
0818:                        // System.out.println("Version info: " + 
0819:                        // Utils.hexEncode(res.enc, (res.idx + 1), res.enc[res.idx]));
0820:                        size = (res.enc[res.idx++] & 0xff);
0821:                        if (res.idx + size > res.enc.length) {
0822:                            throw new IOException("Version info too long");
0823:                        }
0824:
0825:                        // Note: raw version number of 0 means version one
0826:                        res.version = (byte) (res.enc[res.idx + (size - 1)] + 1);
0827:                        res.idx += size;
0828:                    } else {
0829:                        res.version = 1; // No explicit version value
0830:                    }
0831:
0832:                    // Expect the serial number coded as an integer
0833:                    size = res.getLen(INTEGER_TYPE);
0834:                    res.serialNumber = Utils.hexEncode(res.enc, res.idx, size);
0835:                    res.idx += size;
0836:
0837:                    // Expect the signature AlgorithmIdentifier
0838:                    byte id = res.getAlg();
0839:                    // System.out.println("Algorithm Id: " + id);
0840:
0841:                    // Expect the issuer name
0842:                    start = res.idx;
0843:                    size = res.getLen(SEQUENCE_TYPE);
0844:                    int end = res.idx + size;
0845:                    // System.out.println("Issuer: " + 
0846:                    // Utils.hexEncode(res.enc, start, size));
0847:
0848:                    try {
0849:                        res.issuer = res.getName(end);
0850:                    } catch (Exception e) {
0851:                        e.printStackTrace();
0852:                        throw new IOException("Could not parse issuer name");
0853:                    }
0854:
0855:                    // Validity is a sequence of two UTCTime values
0856:                    try {
0857:                        res.match(ValiditySeq);
0858:                        // get start time
0859:                        res.match(UTCSeq);
0860:                        res.from = getUTCTime(res.enc, res.idx);
0861:                        res.idx += UTC_LENGTH;
0862:                        // get end time
0863:                        res.match(UTCSeq);
0864:                        res.until = getUTCTime(res.enc, res.idx);
0865:                        res.idx += UTC_LENGTH;
0866:                    } catch (Exception e) {
0867:                        throw new IOException(
0868:                                "Could not parse validity information"
0869:                                        + "caught " + e);
0870:                    }
0871:
0872:                    // Expect the subject name
0873:                    start = res.idx;
0874:                    size = res.getLen(SEQUENCE_TYPE);
0875:                    end = res.idx + size;
0876:                    // System.out.println("Subject: " +
0877:                    // Utils.hexEncode(res.enc, start, size));
0878:                    if (size != 0) {
0879:                        try {
0880:                            res.subject = res.getName(end);
0881:                            // System.out.println("Subject: " + res.subject);
0882:                        } catch (Exception e) {
0883:                            throw new IOException(
0884:                                    "Could not parse subject name");
0885:                        }
0886:                    } // NOTE: the subject can be null (empty sequence) if
0887:                    // subjectAltName is present
0888:
0889:                    // Parse the subject public key information
0890:                    // System.out.println("SubjectPublicKeyInfo follows");
0891:                    publicKeyLen = res.getLen(SEQUENCE_TYPE);
0892:                    publicKeyPos = res.idx;
0893:
0894:                    // Match the algorithm Id
0895:                    id = res.getAlg();
0896:                    // System.out.println("Public Key Algorithm: " + id);
0897:                    if (id != RSA_ENCRYPTION) {
0898:                        // skip the public key
0899:                        res.idx = publicKeyPos + publicKeyLen;
0900:                    }
0901:
0902:                    // Get the bit string
0903:                    res.getLen(BITSTRING_TYPE);
0904:                    if (res.enc[res.idx++] != 0x00) {
0905:                        throw new IOException(
0906:                                "Bitstring error while parsing public "
0907:                                        + "key information");
0908:                    }
0909:
0910:                    res.getLen(SEQUENCE_TYPE);
0911:                    size = res.getLen(INTEGER_TYPE);
0912:                    if (res.enc[res.idx] == (byte) 0x00) {
0913:                        // strip off the sign byte
0914:                        size--;
0915:                        res.idx++;
0916:                    }
0917:
0918:                    // Build the RSAPublicKey
0919:                    res.pubKey = (RSAPublicKey) KeyBuilder.buildKey(
0920:                            KeyBuilder.TYPE_RSA_PUBLIC, (short) (size << 3),
0921:                            false);
0922:                    res.pubKey.setModulus(res.enc, (short) res.idx,
0923:                            (short) size);
0924:                    // System.out.println("Modulus:  " +
0925:                    // Utils.hexEncode(res.enc, res.idx, size));
0926:                    res.idx += size;
0927:
0928:                    size = res.getLen(INTEGER_TYPE);
0929:                    if (res.enc[res.idx] == (byte) 0x00) {
0930:                        // strip off the sign byte
0931:                        size--;
0932:                        res.idx++;
0933:                    }
0934:                    res.pubKey.setExponent(res.enc, (short) res.idx,
0935:                            (short) size);
0936:                    // System.out.println("Exponent: " +
0937:                    // Utils.hexEncode(res.enc, res.idx, size));
0938:
0939:                    res.idx += size;
0940:                    if (res.idx != sigAlgIdx) {
0941:                        if (res.version < 3) {
0942:                            throw new IOException(
0943:                                    "Unexpected extensions in old version cert");
0944:                        } else {
0945:                            res.parseExtensions(sigAlgIdx);
0946:                        }
0947:                    }
0948:
0949:                    // get the signatureAlgorithm
0950:                    res.sigAlg = res.getAlg();
0951:                    // System.out.println("Signature Algorithm: " + 
0952:                    // res.getSigAlgName());
0953:
0954:                    /*
0955:                     * If this is a supported signature algorithm, compute and save
0956:                     * the hash of TBSCertificate. A null TBSCertHash indicates
0957:                     * the use of an unsupported signature algorithm (see verify())
0958:                     */
0959:                    if (res.sigAlg == MD2_RSA) {
0960:                        MessageDigest md2 = MessageDigest.getInstance(
0961:                                MessageDigest.ALG_MD2, false);
0962:                        res.TBSCertHash = new byte[md2.getLength()];
0963:                        md2.doFinal(buf, off + res.TBSStart, res.TBSLen,
0964:                                res.TBSCertHash, 0);
0965:                    } else if (res.sigAlg == MD5_RSA) {
0966:                        res.TBSCertHash = new byte[md.getLength()];
0967:                        md.doFinal(buf, off + res.TBSStart, res.TBSLen,
0968:                                res.TBSCertHash, 0);
0969:                    } else if (res.sigAlg == SHA1_RSA) {
0970:                        MessageDigest mdSha = MessageDigest.getInstance(
0971:                                MessageDigest.ALG_SHA, false);
0972:                        res.TBSCertHash = new byte[mdSha.getLength()];
0973:                        mdSha.doFinal(buf, (off + res.TBSStart), res.TBSLen,
0974:                                res.TBSCertHash, 0);
0975:                    }
0976:
0977:                    // get the signature
0978:                    size = res.getLen(BITSTRING_TYPE);
0979:                    if (res.enc[res.idx++] != 0x00) {
0980:                        throw new IOException(
0981:                                "Bitstring error in signature parsing");
0982:                    }
0983:
0984:                    /*
0985:                     * We pad the signature to a multiple of 8-bytes before storing
0986:                     * since we only support RSA modulus lengths that are multiples
0987:                     * of 8 bytes and the two should match for decryption to succeed.
0988:                     */
0989:                    int sigLen = (((size - 1) + 7) >>> 3) << 3;
0990:                    res.signature = new byte[sigLen];
0991:                    System.arraycopy(res.enc, res.idx, res.signature,
0992:                            (sigLen - (size - 1)), (size - 1));
0993:                    // System.out.println(sigLen + "-byte signature: " + 
0994:                    // Utils.hexEncode(res.signature));
0995:
0996:                    // long t2 = System.currentTimeMillis();
0997:                    // Utils.logln(Utils.LOG_INFO, "Parsed " + len + " byte cert in " +
0998:                    // (int) (t2 - t1) + " ms");
0999:                    return res;
1000:                } catch (IndexOutOfBoundsException e) {
1001:                    throw new IOException("Bad length detected in cert DER");
1002:                } catch (CryptoException e) {
1003:                    throw new IOException(e.toString());
1004:                }
1005:            }
1006:
1007:            /**
1008:             * Gets the MD5 fingerprint of this certificate.<BR />
1009:             * <b>NOTE:</b> this implementation returns a byte array filled
1010:             * with zeros if there is no fingerprint associated with this
1011:             * certificate. This may happen if a null was passed to the 
1012:             * X509Certificate constructor.
1013:             * <P />
1014:             * @return a byte array containing this certificate's MD5 hash
1015:             */
1016:            public byte[] getFingerprint() {
1017:                byte[] res = new byte[16];
1018:                if (fp != null)
1019:                    System.arraycopy(fp, 0, res, 0, res.length);
1020:                return res;
1021:            }
1022:
1023:            /**
1024:             * Gets the name of this certificate's issuer. <BR />
1025:             * <B>NOTE:</B> The corresponding method in the standard edition
1026:             * is getIssuerDN() and returns a Principal.
1027:             * <P />
1028:             * @return a string containing this certificate's issuer in
1029:             * user-friendly form
1030:             */
1031:            public String getIssuer() {
1032:                return issuer;
1033:            }
1034:
1035:            /**
1036:             * Gets the name of this certificate's subject. <BR />
1037:             * <B>NOTE:</B> The corresponding method in the standard edition
1038:             * is getSubjectDN() and returns a Principal. 
1039:             * <P />
1040:             * @return a string containing this certificate's subject in
1041:             * user-friendly form
1042:             */
1043:            public String getSubject() {
1044:                return subject;
1045:            }
1046:
1047:            /**
1048:             * Gets the NotBefore date from the certificate's validity period.
1049:             * <P />
1050:             * @return a date before which the certificate is not valid
1051:             */
1052:            public long getNotBefore() {
1053:                return from;
1054:            }
1055:
1056:            /**
1057:             * Gets the NotAfter date from the certificate's validity period.
1058:             *
1059:             * @return a date after which the certificate is not valid (expiration
1060:             * date)                                            
1061:             */
1062:            public long getNotAfter() {
1063:                return until;
1064:            }
1065:
1066:            /**
1067:             * Checks if a certificate has any (version 3) extensions that 
1068:             * were not properly processed and continued use of this certificate
1069:             * may be inconsistent with the issuer's intent. This may happen, for
1070:             * example, if the certificate has unrecognized critical extensions. 
1071:             *
1072:             * @exception CertificateException with a reason ofr BAD_EXTENSIONS if
1073:             *    there are any bad extensions
1074:             */
1075:            public void checkExtensions() throws CertificateException {
1076:                if (badExt) {
1077:                    throw new CertificateException(this ,
1078:                            CertificateException.BAD_EXTENSIONS);
1079:                }
1080:            }
1081:
1082:            /** 
1083:             * Checks if the certificate is currently valid. It is if the
1084:             * current date and time are within the certificate's validity
1085:             * period.
1086:             *
1087:             * @exception CertificateException with a reason of 
1088:             *   EXPIRED or NOT_YET_VALID
1089:             */
1090:            public void checkValidity() throws CertificateException {
1091:                checkValidity(System.currentTimeMillis());
1092:            }
1093:
1094:            /** 
1095:             * Checks if the certificate is valid on the specified time. It is
1096:             * if the specified time is within the certificate's validity
1097:             * period. <BR />
1098:             * <B>NOTE:</B> The standard edition provides a method with this
1099:             * name but it throws different types of exceptions rather than
1100:             * returning error codes.
1101:             * <P />
1102:             * @param time the time in milliseconds for which a certificate's
1103:             * validity is to be checked
1104:             *
1105:             * @exception CertificateException with a reason of 
1106:             *   EXPIRED or NOT_YET_VALID
1107:             */
1108:            public void checkValidity(long time) throws CertificateException {
1109:                if (time < from) {
1110:                    throw new CertificateException(this ,
1111:                            CertificateException.NOT_YET_VALID);
1112:                }
1113:
1114:                if (time > until) {
1115:                    throw new CertificateException(this ,
1116:                            CertificateException.EXPIRED);
1117:                }
1118:            }
1119:
1120:            /**
1121:             * Get the type of the <CODE>Certificate</CODE>.
1122:             * @return The type of the <CODE>Certificate</CODE>;
1123:             * the value MUST NOT be <CODE>NULL</CODE>.
1124:             */
1125:            public String getType() {
1126:                return "X.509";
1127:            }
1128:
1129:            /**
1130:             * Gets the public key from this certificate.
1131:             * <P />
1132:             * @return the public key contained in the certificate
1133:             *
1134:             * @exception CertificateException if public key is not a supported type
1135:             *            (could not be parsed).
1136:             */
1137:            public PublicKey getPublicKey() throws CertificateException {
1138:                if (pubKey == null) {
1139:                    throw new CertificateException(this ,
1140:                            CertificateException.UNSUPPORTED_PUBLIC_KEY_TYPE);
1141:                }
1142:
1143:                return pubKey;
1144:            }
1145:
1146:            /**
1147:             * Gets the raw X.509 version number of this certificate. Version 1 is 0.
1148:             *
1149:             * @return the X.509 logic version number (1, 2, 3) of the certificate
1150:             */
1151:            public String getVersion() {
1152:                return Integer.toString(version);
1153:            }
1154:
1155:            /**
1156:             * Gets the certificate constraints path length from the 
1157:             * <code>BasicConstraints</code> extension. <P />
1158:             * 
1159:             * The <code>BasicConstraints</code> extension identifies whether the
1160:             * subject of the certificate is a Certificate Authority (CA) and how
1161:             * deep a certification path may exist through the CA. The
1162:             * <code>pathLenConstraint</code> field (see below) is meaningful only 
1163:             * if <code>cA</code> is set to TRUE. In this case, it gives the maximum
1164:             * number of CA certificates that may follow this certificate in a 
1165:             * certification path. A value of zero indicates that only an end-entity
1166:             * certificate may follow in the path. <P />
1167:             * 
1168:             * Note that for RFC 2459 this extension is always marked critical
1169:             * if <code>cA</code> is TRUE, meaning this certificate belongs to a 
1170:             * Certificate Authority. <P />
1171:             * 
1172:             * The ASN.1 definition for this is:
1173:             * <PRE>
1174:             *  BasicConstraints ::= SEQUENCE {
1175:             *        cA                  BOOLEAN DEFAULT FALSE,
1176:             *        pathLenConstraint   INTEGER (0..MAX) OPTIONAL 
1177:             *  }
1178:             *  </PRE>
1179:             * 
1180:             * @return MISSING_PATH_LENGTH_CONSTRAINT if the
1181:             * <code>BasicConstraints</code> extension is absent or the subject
1182:             * of the certificate is not a CA. If the subject of the certificate
1183:             * is a CA and <code>pathLenConstraint</code> does not appear, 
1184:             * <code>UNLIMITED_CERT_CHAIN_LENGTH</code> is returned to indicate that
1185:             * there is no limit to the allowed length of the certification path.
1186:             * In all other situations, the actual value of the 
1187:             * <code>pathLenConstraint</code> is returned.
1188:             */
1189:            public int getBasicConstraints() {
1190:                if (isCA) {
1191:                    return pLenConstr;
1192:                } else {
1193:                    return MISSING_PATH_LENGTH_CONSTRAINT;
1194:                }
1195:            }
1196:
1197:            /**
1198:             * Gets a 32-bit bit vector (in the form of an integer) in which
1199:             * each position represents a purpose for which the public key in
1200:             * the certificate may be used (iff that bit is set). The correspondence
1201:             * between bit positions and purposes is as follows: <BR />
1202:             * <TABLE>
1203:             * <TR><TD>digitalSignature</TD> <TD>0</TD> </TR>
1204:             * <TR><TD>nonRepudiation</TD>   <TD>1</TD> </TR>
1205:             * <TR><TD>keyEncipherment</TD>  <TD>2</TD> </TR>
1206:             * <TR><TD>dataEncipherment</TD> <TD>3</TD> </TR>
1207:             * <TR><TD>keyAgreement</TD>     <TD>4</TD> </TR>
1208:             * <TR><TD>keyCertSign</TD>      <TD>5</TD> </TR>
1209:             * <TR><TD>cRLSign</TD>          <TD>6</TD> </TR>
1210:             * <TR><TD>encipherOnly</TD>     <TD>7</TD> </TR>
1211:             * <TR><TD>decipherOnly</TD>     <TD>8</TD> </TR>
1212:             * <TR><TD>serverAuth</TD>       <TD>17</TD> </TR>
1213:             * <TR><TD>clientAuth</TD>       <TD>18</TD> </TR>
1214:             * <TR><TD>codeSigning</TD>      <TD>19</TD> </TR>
1215:             * <TR><TD>emailProtection</TD>  <TD>20</TD> </TR>
1216:             * <TR><TD>ipsecEndSystem</TD>   <TD>21</TD> </TR>
1217:             * <TR><TD>ipsecTunnel</TD>      <TD>22</TD> </TR>
1218:             * <TR><TD>ipsecUser</TD>        <TD>23</TD> </TR>
1219:             * <TR><TD>timeStamping</TD>     <TD>24</TD> </TR>
1220:             * </TABLE>
1221:             * <P />
1222:             * @return a bitvector indicating approved usage of the certificate
1223:             * public key, -1 if neither a KeyUsage nor a critical extendedKeyUsage
1224:             * extension is present.
1225:             */
1226:            public int getKeyUsage() {
1227:                return ((int) keyUsage);
1228:            }
1229:
1230:            /**
1231:             * Gets the type of subject alternative name.
1232:             *
1233:             * @return type of subject alternative name
1234:             */
1235:            public int getSubjectAltNameType() {
1236:                return subAltNameType;
1237:            }
1238:
1239:            /**
1240:             * Gets the subject alternative name or null if it was not in the 
1241:             * certificate.
1242:             *
1243:             * @return type of subject alternative name or null
1244:             */
1245:            public Object getSubjectAltName() {
1246:                return subAltName;
1247:            }
1248:
1249:            /**
1250:             * Gets the printable form of the serial number of this
1251:             * <CODE>Certificate</CODE>. 
1252:             * If the serial number within the <CODE>certificate</CODE>
1253:             * is binary is should be formatted as a string using
1254:             * hexadecimal notation with each byte represented as two
1255:             * hex digits separated byte ":" (Unicode x3A).
1256:             * For example,  27:56:FA:80.
1257:             * @return A string containing the serial number
1258:             * in user-friendly form; <CODE>NULL</CODE> is returned
1259:             * if there is no serial number.
1260:             */
1261:            public String getSerialNumber() {
1262:                return serialNumber;
1263:            }
1264:
1265:            /**
1266:             * Checks if this certificate was signed using the private key
1267:             * corresponding to the specified public key.
1268:             *
1269:             * @param pk public key to be used for verifying certificate signature
1270:             *
1271:             * @exception CertificateException if there is an error
1272:             */
1273:            public void verify(PublicKey pk) throws CertificateException {
1274:
1275:                if (pk.getType() != KeyBuilder.TYPE_RSA_PUBLIC) {
1276:                    throw new CertificateException(
1277:                            "Issuer key not a public RSA", this ,
1278:                            CertificateException.VERIFICATION_FAILED);
1279:                }
1280:
1281:                /*
1282:                 * Since selfSigned certificates are stored without
1283:                 * TBSCertHash and signature fields (to save memory),
1284:                 * the only way to return anything meaningful is by
1285:                 * directly comparing the specified public key against
1286:                 * the certificate public key. This allows us to return
1287:                 * the right result even on certificates created using
1288:                 * the Certificate(...) constructor.
1289:                 * 
1290:                 * NOTE: We can comment this out to save code here and
1291:                 * in Key (and its subclasses) -- no need to define equals
1292:                 * The documentation already warns users not to invoke
1293:                 * verify() on certificates with null signature.
1294:                 */
1295:                if (selfSigned) {
1296:                    if (pubKey.equals((RSAPublicKey) pk)) {
1297:                        return;
1298:                    }
1299:
1300:                    throw new CertificateException("Bad self signed cert",
1301:                            this , CertificateException.VERIFICATION_FAILED);
1302:                }
1303:
1304:                if (signature == null) {
1305:                    throw new CertificateException(this ,
1306:                            CertificateException.MISSING_SIGNATURE);
1307:                }
1308:
1309:                if (TBSCertHash == null) {
1310:                    throw new CertificateException(this ,
1311:                            CertificateException.UNSUPPORTED_SIGALG);
1312:                }
1313:
1314:                // long t1 = System.currentTimeMillis();
1315:                int modLen = pk.getSize() >>> 3;
1316:                byte[] result = new byte[modLen];
1317:
1318:                int val;
1319:
1320:                /*
1321:                 * NOTE: We can not use the Signature class because, at this 
1322:                 * point, we do not have TBSCertificate (just its hash). The 
1323:                 * Signature class needs raw data and computes a hash internally.
1324:                 */
1325:                try {
1326:                    Cipher rsa = Cipher
1327:                            .getInstance(Cipher.ALG_RSA_PKCS1, false);
1328:                    rsa.init(pk, Cipher.MODE_DECRYPT);
1329:                    val = rsa
1330:                            .doFinal(signature, 0, signature.length, result, 0);
1331:                } catch (Exception e) {
1332:                    throw new CertificateException(this ,
1333:                            CertificateException.VERIFICATION_FAILED);
1334:                }
1335:
1336:                /*
1337:                 * NOTE: the decrypted value includes an ASN DER
1338:                 * encoding of
1339:                 * DigestInfo ::= SEQUENCE {
1340:                 *       digestAlgorithm DigestAlgorithmIdentifier,
1341:                 *       digest Digest }
1342:                 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
1343:                 * Digest ::= OCTET STRING
1344:                 * 
1345:                 * For md2WithRSAEncryption, the decrypted value will be
1346:                 * 3020300c06082a864886f70d020205000410 followed by a 16-byte hash
1347:                 *
1348:                 * For md5WithRSAEncryption, the decrypted value will be
1349:                 * 3020300c06082a864886f70d020505000410 followed by a 16-byte hash
1350:                 *   30 20      32: SEQUENCE
1351:                 *   30 0c      12: . SEQUENCE
1352:                 *   06 08       8: . . OID 1.2.840.113549.2.5 (MD5 OID, rfc2313 pg 14)
1353:                 *                : 2a 86 48 86 f7 0d 02 05
1354:                 *   05 00       0: . . NULL (null parameters)
1355:                 *   04 10      16: . OCTET STRING
1356:                 *                :  <the hash gos here>
1357:                 *
1358:                 * Similarly, for SHA-1, the 20-byte hash will be preceded by
1359:                 * 3021300906052b0e03021a05000414
1360:                 * 30 21       33: SEQUENCE
1361:                 * 30 09        9: . SEQUENCE
1362:                 * 06 05        5: . . OID 1.3.14.3.2.26 (SHA-1 digest OID)
1363:                 *              0: 2b 0e 03 02 1a
1364:                 * 05 00        0: . . NULL (null parameters)
1365:                 * 04 14       20: . <20-byte hash>
1366:                 */
1367:                if ((sigAlg == MD2_RSA)
1368:                        && (val == (PREFIX_MD2.length + TBSCertHash.length))
1369:                        && Utils.byteMatch(result, 0, PREFIX_MD2, 0,
1370:                                PREFIX_MD2.length)
1371:                        && Utils.byteMatch(result, PREFIX_MD2.length,
1372:                                TBSCertHash, 0, TBSCertHash.length)) {
1373:                    return;
1374:                }
1375:
1376:                if ((sigAlg == MD5_RSA)
1377:                        && (val == (PREFIX_MD5.length + TBSCertHash.length))
1378:                        && Utils.byteMatch(result, 0, PREFIX_MD5, 0,
1379:                                PREFIX_MD5.length)
1380:                        && Utils.byteMatch(result, PREFIX_MD5.length,
1381:                                TBSCertHash, 0, TBSCertHash.length)) {
1382:                    return;
1383:                }
1384:
1385:                if ((sigAlg == SHA1_RSA)
1386:                        && (val == (PREFIX_SHA1.length + TBSCertHash.length))
1387:                        && Utils.byteMatch(result, 0, PREFIX_SHA1, 0,
1388:                                PREFIX_SHA1.length)
1389:                        && Utils.byteMatch(result, PREFIX_SHA1.length,
1390:                                TBSCertHash, 0, TBSCertHash.length)) {
1391:                    return;
1392:                }
1393:
1394:                throw new CertificateException(this ,
1395:                        CertificateException.VERIFICATION_FAILED);
1396:            }
1397:
1398:            /**
1399:             * Gets the name of the algorithm used to sign the certificate.
1400:             * <P />
1401:             * @return the name of signature algorithm
1402:             */
1403:            public String getSigAlgName() {
1404:                /* 
1405:                 * These are ordered to maximize the likelihood of an
1406:                 * early match, md5WithRSA seems the most common
1407:                 */
1408:                if (sigAlg == MD5_RSA)
1409:                    return ("MD5withRSA");
1410:                else if (sigAlg == MD2_RSA)
1411:                    return ("MD2withRSA");
1412:                else if (sigAlg == SHA1_RSA)
1413:                    return ("SHA1withRSA");
1414:                else if (sigAlg == NONE)
1415:                    return ("None");
1416:                else if (sigAlg == MD4_RSA)
1417:                    return ("MD4withRSA");
1418:                else
1419:                    return ("Unknown (" + sigAlg + ")");
1420:            }
1421:
1422:            /** Array of purpose strings describing key usage role. */
1423:            private static final String[] KEY_USAGE = { "digitalSignature", // 0
1424:                    "nonRepudiation", // 1
1425:                    "keyEncipherment", // 2
1426:                    "dataEncipherment", // 3
1427:                    "keyAgreement", // 4
1428:                    "keyCertSign", // 5
1429:                    "cRLSign", // 6
1430:                    "encipherOnly", // 7
1431:                    "decipherOnly", // 8
1432:                    // below are for the extended key usage extension
1433:                    "9", "10", "11", "12", "13", "14", "15", "16", // 9-16
1434:                    "serverAuth", // 17
1435:                    "clientAuth", // 18
1436:                    "codeSigning", // 19
1437:                    "emailProtection", // 20
1438:                    "ipsecEndSystem", // 21
1439:                    "ipsecTunnel", // 22
1440:                    "ipsecUser", // 23
1441:                    "timeStamping" // 24
1442:            };
1443:
1444:            /**
1445:             * Converts a Date object to a string containing the corresponding 
1446:             * date.<br />
1447:             * <b>NOTE:</b> This is here only because the J2ME date class does not
1448:             * implement toString() in any meaningful way.
1449:             * <p />
1450:             * @param date Date object to be converted
1451:             * @return a string representation of the Date object in
1452:             *         the form "month/day/year hour:min:sec"
1453:             */
1454:            private static String date2str(Date date) {
1455:                Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
1456:                c.setTime(date);
1457:                String d = (c.get(Calendar.MONTH) + 1) + "/"
1458:                        + c.get(Calendar.DAY_OF_MONTH) + "/"
1459:                        + c.get(Calendar.YEAR) + " "
1460:                        + c.get(Calendar.HOUR_OF_DAY) + ":"
1461:                        + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND);
1462:                return d;
1463:            }
1464:
1465:            /**
1466:             * Returns a string representation of this certificate.
1467:             * <p />
1468:             * @return a human readable string repesentation of this certificate
1469:             */
1470:            public String toString() {
1471:                StringBuffer tmp = new StringBuffer();
1472:
1473:                tmp.append("[Type: ");
1474:                tmp.append(getType());
1475:                tmp.append("v");
1476:                tmp.append(version);
1477:
1478:                tmp.append("\n");
1479:                tmp.append("Serial number: ");
1480:                tmp.append(serialNumber);
1481:
1482:                tmp.append("\n");
1483:                tmp.append("Subject: ");
1484:                tmp.append(subject);
1485:
1486:                tmp.append("\n");
1487:                tmp.append("Issuer: ");
1488:                tmp.append(issuer);
1489:
1490:                tmp.append("\n");
1491:                tmp.append("Valid from ");
1492:                tmp.append(date2str(new Date(getNotBefore())));
1493:                tmp.append(" GMT until ");
1494:                tmp.append(date2str(new Date(getNotAfter())));
1495:                tmp.append(" GMT");
1496:
1497:                // tmp.append("\n");
1498:                // tmp.append(pubKey.toString());
1499:
1500:                // tmp.append("\n");
1501:                // tmp.append(TBSCertificate hash: ");
1502:                // tmp.append(TBSCertHash == null ?
1503:                //           "null" : Utils.hexEncode(TBSCertHash));
1504:
1505:                tmp.append("\n");
1506:                tmp.append("Signature Algorithm: ");
1507:                tmp.append(getSigAlgName());
1508:
1509:                if (subAltName != null) {
1510:                    tmp.append("\n");
1511:                    tmp.append("SubjectAltName: ");
1512:                    tmp.append(subAltName);
1513:                    tmp.append("(type ");
1514:                    tmp.append(subAltNameType);
1515:                    tmp.append(")");
1516:                }
1517:
1518:                if (keyUsage != -1) {
1519:                    tmp.append("\n");
1520:                    tmp.append("KeyUsage:");
1521:                    int t = (int) keyUsage;
1522:                    for (int i = 0; i < KEY_USAGE.length; i++) {
1523:                        if ((t & 0x01) == 0x01) {
1524:                            tmp.append(" ");
1525:                            tmp.append(KEY_USAGE[i]);
1526:                        }
1527:
1528:                        t = t >>> 1;
1529:                    }
1530:                }
1531:
1532:                if (hasBC) {
1533:                    tmp.append("\n");
1534:                    tmp.append("BasicConstraints: ");
1535:                    tmp.append(isCA ? "is a CA" : "not a CA");
1536:                    tmp.append(" (pathLengthConstraint ");
1537:                    if ((pLenConstr == MISSING_PATH_LENGTH_CONSTRAINT)
1538:                            || (pLenConstr == UNLIMITED_CERT_CHAIN_LENGTH)) {
1539:                        tmp.append("absent");
1540:                    } else {
1541:                        tmp.append(pLenConstr);
1542:                    }
1543:
1544:                    tmp.append(")");
1545:                }
1546:
1547:                // tmp.append("\n");
1548:                // tmp.append("MD5 Fingerprint: ");
1549:                // tmp.append(Utils.hexEncode(fp));
1550:                tmp.append("]");
1551:                return tmp.toString();
1552:            }
1553:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.