995 lines · 33.9 KB · Java
RawDownload
/* * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.x509; import java.io.IOException;import java.io.OutputStream; import java.security.cert.*;import java.util.*; import sun.security.util.*;import sun.misc.HexDumpEncoder;  /** * The X509CertInfo class represents X.509 certificate information. * * <P>X.509 certificates have several base data elements, including:<UL> * * <LI>The <em>Subject Name</em>, an X.500 Distinguished Name for *      the entity (subject) for which the certificate was issued. * * <LI>The <em>Subject Public Key</em>, the public key of the subject. *      This is one of the most important parts of the certificate. * * <LI>The <em>Validity Period</em>, a time period (e.g. six months) *      within which the certificate is valid (unless revoked). * * <LI>The <em>Issuer Name</em>, an X.500 Distinguished Name for the *      Certificate Authority (CA) which issued the certificate. * * <LI>A <em>Serial Number</em> assigned by the CA, for use in *      certificate revocation and other applications. * * @author Amit Kapoor * @author Hemma Prafullchandra * @see CertAttrSet * @see X509CertImpl */public class X509CertInfo implements CertAttrSet<String> {    /**     * Identifier for this attribute, to be used with the     * get, set, delete methods of Certificate, x509 type.     */    public static final String IDENT = "x509.info";    // Certificate attribute names    public static final String NAME = "info";    public static final String VERSION = CertificateVersion.NAME;    public static final String SERIAL_NUMBER = CertificateSerialNumber.NAME;    public static final String ALGORITHM_ID = CertificateAlgorithmId.NAME;    public static final String ISSUER = CertificateIssuerName.NAME;    public static final String VALIDITY = CertificateValidity.NAME;    public static final String SUBJECT = CertificateSubjectName.NAME;    public static final String KEY = CertificateX509Key.NAME;    public static final String ISSUER_ID = CertificateIssuerUniqueIdentity.NAME;    public static final String SUBJECT_ID = CertificateSubjectUniqueIdentity.NAME;    public static final String EXTENSIONS = CertificateExtensions.NAME;     // X509.v1 data    protected CertificateVersion version = new CertificateVersion();    protected CertificateSerialNumber   serialNum = null;    protected CertificateAlgorithmId    algId = null;    protected CertificateIssuerName     issuer = null;    protected CertificateValidity       interval = null;    protected CertificateSubjectName    subject = null;    protected CertificateX509Key        pubKey = null;     // X509.v2 & v3 extensions    protected CertificateIssuerUniqueIdentity   issuerUniqueId = null;    protected CertificateSubjectUniqueIdentity  subjectUniqueId = null;     // X509.v3 extensions    protected CertificateExtensions     extensions = null;     // Attribute numbers for internal manipulation    private static final int ATTR_VERSION = 1;    private static final int ATTR_SERIAL = 2;    private static final int ATTR_ALGORITHM = 3;    private static final int ATTR_ISSUER = 4;    private static final int ATTR_VALIDITY = 5;    private static final int ATTR_SUBJECT = 6;    private static final int ATTR_KEY = 7;    private static final int ATTR_ISSUER_ID = 8;    private static final int ATTR_SUBJECT_ID = 9;    private static final int ATTR_EXTENSIONS = 10;     // DER encoded CertificateInfo data    private byte[]      rawCertInfo = null;     // The certificate attribute name to integer mapping stored here    private static final Map<String,Integer> map = new HashMap<String,Integer>();    static {        map.put(VERSION, Integer.valueOf(ATTR_VERSION));        map.put(SERIAL_NUMBER, Integer.valueOf(ATTR_SERIAL));        map.put(ALGORITHM_ID, Integer.valueOf(ATTR_ALGORITHM));        map.put(ISSUER, Integer.valueOf(ATTR_ISSUER));        map.put(VALIDITY, Integer.valueOf(ATTR_VALIDITY));        map.put(SUBJECT, Integer.valueOf(ATTR_SUBJECT));        map.put(KEY, Integer.valueOf(ATTR_KEY));        map.put(ISSUER_ID, Integer.valueOf(ATTR_ISSUER_ID));        map.put(SUBJECT_ID, Integer.valueOf(ATTR_SUBJECT_ID));        map.put(EXTENSIONS, Integer.valueOf(ATTR_EXTENSIONS));    }     /**     * Construct an uninitialized X509CertInfo on which <a href="#decode">     * decode</a> must later be called (or which may be deserialized).     */    public X509CertInfo() { }     /**     * Unmarshals a certificate from its encoded form, parsing the     * encoded bytes.  This form of constructor is used by agents which     * need to examine and use certificate contents.  That is, this is     * one of the more commonly used constructors.  Note that the buffer     * must include only a certificate, and no "garbage" may be left at     * the end.  If you need to ignore data at the end of a certificate,     * use another constructor.     *     * @param cert the encoded bytes, with no trailing data.     * @exception CertificateParsingException on parsing errors.     */    public X509CertInfo(byte[] cert) throws CertificateParsingException {        try {            DerValue    in = new DerValue(cert);             parse(in);        } catch (IOException e) {            CertificateParsingException parseException =                        new CertificateParsingException(e.toString());            parseException.initCause(e);            throw parseException;        }    }     /**     * Unmarshal a certificate from its encoded form, parsing a DER value.     * This form of constructor is used by agents which need to examine     * and use certificate contents.     *     * @param derVal the der value containing the encoded cert.     * @exception CertificateParsingException on parsing errors.     */    public X509CertInfo(DerValue derVal) throws CertificateParsingException {        try {            parse(derVal);        } catch (IOException e) {            CertificateParsingException parseException =                        new CertificateParsingException(e.toString());            parseException.initCause(e);            throw parseException;        }    }     /**     * Appends the certificate to an output stream.     *     * @param out an output stream to which the certificate is appended.     * @exception CertificateException on encoding errors.     * @exception IOException on other errors.     */    public void encode(OutputStream out)    throws CertificateException, IOException {        if (rawCertInfo == null) {            DerOutputStream tmp = new DerOutputStream();            emit(tmp);            rawCertInfo = tmp.toByteArray();        }        out.write(rawCertInfo.clone());    }     /**     * Return an enumeration of names of attributes existing within this     * attribute.     */    public Enumeration<String> getElements() {        AttributeNameEnumeration elements = new AttributeNameEnumeration();        elements.addElement(VERSION);        elements.addElement(SERIAL_NUMBER);        elements.addElement(ALGORITHM_ID);        elements.addElement(ISSUER);        elements.addElement(VALIDITY);        elements.addElement(SUBJECT);        elements.addElement(KEY);        elements.addElement(ISSUER_ID);        elements.addElement(SUBJECT_ID);        elements.addElement(EXTENSIONS);         return elements.elements();    }     /**     * Return the name of this attribute.     */    public String getName() {        return(NAME);    }     /**     * Returns the encoded certificate info.     *     * @exception CertificateEncodingException on encoding information errors.     */    public byte[] getEncodedInfo() throws CertificateEncodingException {        try {            if (rawCertInfo == null) {                DerOutputStream tmp = new DerOutputStream();                emit(tmp);                rawCertInfo = tmp.toByteArray();            }            return rawCertInfo.clone();        } catch (IOException e) {            throw new CertificateEncodingException(e.toString());        } catch (CertificateException e) {            throw new CertificateEncodingException(e.toString());        }    }     /**     * Compares two X509CertInfo objects.  This is false if the     * certificates are not both X.509 certs, otherwise it     * compares them as binary data.     *     * @param other the object being compared with this one     * @return true iff the certificates are equivalent     */    public boolean equals(Object other) {        if (other instanceof X509CertInfo) {            return equals((X509CertInfo) other);        } else {            return false;        }    }     /**     * Compares two certificates, returning false if any data     * differs between the two.     *     * @param other the object being compared with this one     * @return true iff the certificates are equivalent     */    public boolean equals(X509CertInfo other) {        if (this == other) {            return(true);        } else if (rawCertInfo == null || other.rawCertInfo == null) {            return(false);        } else if (rawCertInfo.length != other.rawCertInfo.length) {            return(false);        }        for (int i = 0; i < rawCertInfo.length; i++) {            if (rawCertInfo[i] != other.rawCertInfo[i]) {                return(false);            }        }        return(true);    }     /**     * Calculates a hash code value for the object.  Objects     * which are equal will also have the same hashcode.     */    public int hashCode() {        int     retval = 0;         for (int i = 1; i < rawCertInfo.length; i++) {            retval += rawCertInfo[i] * i;        }        return(retval);    }     /**     * Returns a printable representation of the certificate.     */    public String toString() {         if (subject == null || pubKey == null || interval == null            || issuer == null || algId == null || serialNum == null) {                throw new NullPointerException("X.509 cert is incomplete");        }        StringBuilder sb = new StringBuilder();         sb.append("[\n");        sb.append("  " + version.toString() + "\n");        sb.append("  Subject: " + subject.toString() + "\n");        sb.append("  Signature Algorithm: " + algId.toString() + "\n");        sb.append("  Key:  " + pubKey.toString() + "\n");        sb.append("  " + interval.toString() + "\n");        sb.append("  Issuer: " + issuer.toString() + "\n");        sb.append("  " + serialNum.toString() + "\n");         // optional v2, v3 extras        if (issuerUniqueId != null) {            sb.append("  Issuer Id:\n" + issuerUniqueId.toString() + "\n");        }        if (subjectUniqueId != null) {            sb.append("  Subject Id:\n" + subjectUniqueId.toString() + "\n");        }        if (extensions != null) {            Collection allExts = extensions.getAllExtensions();            Object[] objs = allExts.toArray();            sb.append("\nCertificate Extensions: " + objs.length);            for (int i = 0; i < objs.length; i++) {                sb.append("\n[" + (i+1) + "]: ");                Extension ext = (Extension)objs[i];                try {                    if (OIDMap.getClass(ext.getExtensionId()) == null) {                        sb.append(ext.toString());                        byte[] extValue = ext.getExtensionValue();                        if (extValue != null) {                            DerOutputStream out = new DerOutputStream();                            out.putOctetString(extValue);                            extValue = out.toByteArray();                            HexDumpEncoder enc = new HexDumpEncoder();                            sb.append("Extension unknown: "                                      + "DER encoded OCTET string =\n"                                      + enc.encodeBuffer(extValue) + "\n");                        }                    } else                        sb.append(ext.toString()); //sub-class exists                } catch (Exception e) {                    sb.append(", Error parsing this extension");                }            }            Map<String,Extension> invalid = extensions.getUnparseableExtensions();            if (invalid.isEmpty() == false) {                sb.append("\nUnparseable certificate extensions: " + invalid.size());                int i = 1;                for (Extension ext : invalid.values()) {                    sb.append("\n[" + (i++) + "]: ");                    sb.append(ext);                }            }        }        sb.append("\n]");        return sb.toString();    }     /**     * Set the certificate attribute.     *     * @params name the name of the Certificate attribute.     * @params val the value of the Certificate attribute.     * @exception CertificateException on invalid attributes.     * @exception IOException on other errors.     */    public void set(String name, Object val)    throws CertificateException, IOException {        X509AttributeName attrName = new X509AttributeName(name);         int attr = attributeMap(attrName.getPrefix());        if (attr == 0) {            throw new CertificateException("Attribute name not recognized: "                                           + name);        }        // set rawCertInfo to null, so that we are forced to re-encode        rawCertInfo = null;        String suffix = attrName.getSuffix();         switch (attr) {        case ATTR_VERSION:            if (suffix == null) {                setVersion(val);            } else {                version.set(suffix, val);            }            break;         case ATTR_SERIAL:            if (suffix == null) {                setSerialNumber(val);            } else {                serialNum.set(suffix, val);            }            break;         case ATTR_ALGORITHM:            if (suffix == null) {                setAlgorithmId(val);            } else {                algId.set(suffix, val);            }            break;         case ATTR_ISSUER:            if (suffix == null) {                setIssuer(val);            } else {                issuer.set(suffix, val);            }            break;         case ATTR_VALIDITY:            if (suffix == null) {                setValidity(val);            } else {                interval.set(suffix, val);            }            break;         case ATTR_SUBJECT:            if (suffix == null) {                setSubject(val);            } else {                subject.set(suffix, val);            }            break;         case ATTR_KEY:            if (suffix == null) {                setKey(val);            } else {                pubKey.set(suffix, val);            }            break;         case ATTR_ISSUER_ID:            if (suffix == null) {                setIssuerUniqueId(val);            } else {                issuerUniqueId.set(suffix, val);            }            break;         case ATTR_SUBJECT_ID:            if (suffix == null) {                setSubjectUniqueId(val);            } else {                subjectUniqueId.set(suffix, val);            }            break;         case ATTR_EXTENSIONS:            if (suffix == null) {                setExtensions(val);            } else {                if (extensions == null)                    extensions = new CertificateExtensions();                extensions.set(suffix, val);            }            break;        }    }     /**     * Delete the certificate attribute.     *     * @params name the name of the Certificate attribute.     * @exception CertificateException on invalid attributes.     * @exception IOException on other errors.     */    public void delete(String name)    throws CertificateException, IOException {        X509AttributeName attrName = new X509AttributeName(name);         int attr = attributeMap(attrName.getPrefix());        if (attr == 0) {            throw new CertificateException("Attribute name not recognized: "                                           + name);        }        // set rawCertInfo to null, so that we are forced to re-encode        rawCertInfo = null;        String suffix = attrName.getSuffix();         switch (attr) {        case ATTR_VERSION:            if (suffix == null) {                version = null;            } else {                version.delete(suffix);            }            break;        case (ATTR_SERIAL):            if (suffix == null) {                serialNum = null;            } else {                serialNum.delete(suffix);            }

Lines 1–500 of 995.