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


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