x509factory.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 750 行 · 第 1/2 页

JAVA
750
字号
/* * @(#)X509Factory.java	1.4 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program 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.    *    * This program 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 at /legal/license.txt).    *    * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * *//* * Note that there are two versions of X509Factory, this subsetted * version for CDC/FP and another for the security optional package. * Be sure you're editing the right one! */package sun.security.provider;import java.io.*;import java.util.Collection;import java.util.*;import java.security.cert.*;import sun.security.x509.X509CertImpl;import sun.security.x509.X509CRLImpl;import sun.security.pkcs.PKCS7;import sun.security.provider.certpath.X509CertPath;// CDC/FP X509CertificatePair subsetted out for space savings.// import sun.security.provider.certpath.X509CertificatePair;import sun.security.util.DerValue;import sun.security.util.Cache;import sun.misc.BASE64Decoder;/** * This class defines a certificate factory for X.509 v3 certificates & * certification paths, and X.509 v2 certificate revocation lists (CRLs). * * @author Jan Luehe * @author Hemma Prafullchandra * @author Sean Mullan * * @version 1.4, 10/10/06 * * @see java.security.cert.CertificateFactorySpi * @see java.security.cert.Certificate * @see java.security.cert.CertPath * @see java.security.cert.CRL * @see java.security.cert.X509Certificate * @see java.security.cert.X509CRL * @see sun.security.x509.X509CertImpl * @see sun.security.x509.X509CRLImpl */public class X509Factory extends CertificateFactorySpi {    public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";    public static final String END_CERT = "-----END CERTIFICATE-----";    private static final int defaultExpectedLineLength = 80;    private static final char[] endBoundary = "-----END".toCharArray();        private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX        private static final Cache certCache = Cache.newSoftMemoryCache(750);    private static final Cache crlCache = Cache.newSoftMemoryCache(750);    /**     * Generates an X.509 certificate object and initializes it with     * the data read from the input stream <code>is</code>.     *     * @param is an input stream with the certificate data.     *     * @return an X.509 certificate object initialized with the data     * from the input stream.     *     * @exception CertificateException on parsing errors.     */    public Certificate engineGenerateCertificate(InputStream is)	throws CertificateException    {	if (is == null) {	    // clear the caches (for debugging)	    certCache.clear();            // CDC/FP - X509CertificatePair has been subsetted            // out to save space.	    // X509CertificatePair.clearCache();	    throw new CertificateException("Missing input stream");	}	try {	    if (is.markSupported() == false) {		// consume the entire input stream		byte[] totalBytes;		totalBytes = getTotalBytes(new BufferedInputStream(is));		is = new ByteArrayInputStream(totalBytes);	    }	    byte[] encoding = readSequence(is);	    if (encoding != null) {		X509CertImpl cert = (X509CertImpl)getFromCache(certCache, encoding);		if (cert != null) {		    return cert;		}		cert = new X509CertImpl(encoding);		addToCache(certCache, cert.getEncodedInternal(), cert);		return cert;	    } else {		X509CertImpl cert;		// determine if binary or Base64 encoding. If Base64 encoding,		// the certificate must be bounded at the beginning by		// "-----BEGIN".		if (isBase64(is)) {		    // Base64		    byte[] data = base64_to_binary(is);		    cert = new X509CertImpl(data);		} else {		    // binary		    cert = new X509CertImpl(new DerValue(is));		}		return intern(cert);	    }	} catch (IOException ioe) {	    throw (CertificateException)new CertificateException	    ("Could not parse certificate: " + ioe.toString()).initCause(ioe);	}    }        /**     * Read a DER SEQUENCE from an InputStream and return the encoding.     * If data does not represent a SEQUENCE, it uses indefinite length     * encoding, or is longer than ENC_MAX_LENGTH, the stream is reset     * and this method returns null.     */    private static byte[] readSequence(InputStream in) throws IOException {	in.mark(ENC_MAX_LENGTH);	byte[] b = new byte[4];	int i = readFully(in, b, 0, b.length);	if ((i != b.length) || (b[0] != 0x30)) { // first byte must be SEQUENCE	    in.reset();	    return null;	}	i = b[1] & 0xff;	int totalLength;	if (i < 0x80) {	    int valueLength = i;	    totalLength = valueLength + 2;	} else if (i == 0x81) {	    int valueLength = b[2] & 0xff;	    totalLength = valueLength + 3;	} else if (i == 0x82) {	    int valueLength = ((b[2] & 0xff) << 8) | (b[3] & 0xff);	    totalLength = valueLength + 4;	} else { // ignore longer length forms	    in.reset();	    return null;	}	if (totalLength > ENC_MAX_LENGTH) {	    in.reset();	    return null;	}	byte[] encoding = new byte[totalLength];	System.arraycopy(b, 0, encoding, 0, b.length);	int n = totalLength - b.length;	i = readFully(in, encoding, b.length, n);	if (i != n) {	    in.reset();	    return null;	}	return encoding;    }        /**     * Read from the stream until length bytes have been read or EOF has     * been reached. Return the number of bytes actually read.     */    private static int readFully(InputStream in, byte[] buffer, int offset, 	    int length) throws IOException {	int read = 0;	while (length > 0) {	    int n = in.read(buffer, offset, length);	    if (n <= 0) {		break;	    }	    read += n;	    length -= n;	    offset += n;	}	return read;    }        /**     * Return an interned X509CertImpl for the given certificate.     * If the given X509Certificate or X509CertImpl is already present     * in the cert cache, the cached object is returned. Otherwise,     * if it is a X509Certificate, it is first converted to a X509CertImpl.     * Then the X509CertImpl is added to the cache and returned.     *     * Note that all certificates created via generateCertificate(InputStream)     * are already interned and this method does not need to be called.     * It is useful for certificates that cannot be created via     * generateCertificate() and for converting other X509Certificate      * implementations to an X509CertImpl.     */    public static synchronized X509CertImpl intern(X509Certificate c)	    throws CertificateException {	if (c == null) {	    return null;	}	boolean isImpl = c instanceof X509CertImpl;	byte[] encoding;	if (isImpl) {	    encoding = ((X509CertImpl)c).getEncodedInternal();	} else {	    encoding = c.getEncoded();	}	X509CertImpl newC = (X509CertImpl)getFromCache(certCache, encoding);	if (newC != null) {	    return newC;	}	if (isImpl) {	    newC = (X509CertImpl)c;	} else {	    newC = new X509CertImpl(encoding);	    encoding = newC.getEncodedInternal();	}	addToCache(certCache, encoding, newC);	return newC;    }        /**     * Return an interned X509CRLImpl for the given certificate.     * For more information, see intern(X509Certificate).     */    public static synchronized X509CRLImpl intern(X509CRL c)	    throws CRLException {	if (c == null) {	    return null;	}	boolean isImpl = c instanceof X509CRLImpl;	byte[] encoding;	if (isImpl) {	    encoding = ((X509CRLImpl)c).getEncodedInternal();	} else {	    encoding = c.getEncoded();	}	X509CRLImpl newC = (X509CRLImpl)getFromCache(crlCache, encoding);	if (newC != null) {	    return newC;	}	if (isImpl) {	    newC = (X509CRLImpl)c;	} else {	    newC = new X509CRLImpl(encoding);	    encoding = newC.getEncodedInternal();	}	addToCache(crlCache, encoding, newC);	return newC;    }        /**     * Get the X509CertImpl or X509CRLImpl from the cache.     */    private static synchronized Object getFromCache(Cache cache,	    byte[] encoding) {	Object key = new Cache.EqualByteArray(encoding);	Object value = cache.get(key);	return value;    }        /**     * Add the X509CertImpl or X509CRLImpl to the cache.     */    private static synchronized void addToCache(Cache cache, byte[] encoding,	    Object value) {	if (encoding.length > ENC_MAX_LENGTH) {	    return;	}	Object key = new Cache.EqualByteArray(encoding);	cache.put(key, value);    }    /**     * Generates a <code>CertPath</code> object and initializes it with     * the data read from the <code>InputStream</code> inStream. The data     * is assumed to be in the default encoding.     *     * @param inStream an <code>InputStream</code> containing the data     * @return a <code>CertPath</code> initialized with the data from the     *   <code>InputStream</code>     * @exception CertificateException if an exception occurs while decoding     * @since 1.4     */    public CertPath engineGenerateCertPath(InputStream inStream)        throws CertificateException    {        if (inStream == null) {            throw new CertificateException("Missing input stream");        }        try {            if (inStream.markSupported() == false) {                // consume the entire input stream                byte[] totalBytes;                totalBytes = getTotalBytes(new BufferedInputStream(inStream));                inStream = new ByteArrayInputStream(totalBytes);            }            // determine if binary or Base64 encoding. If Base64 encoding,            // each certificate must be bounded at the beginning by            // "-----BEGIN".            if (isBase64(inStream)) {                // Base64                byte[] data = base64_to_binary(inStream);                return new X509CertPath(new ByteArrayInputStream(data));            } else {                return new X509CertPath(inStream);            }        } catch (IOException ioe) {            throw new CertificateException(ioe.getMessage());        }    }    /**     * Generates a <code>CertPath</code> object and initializes it with     * the data read from the <code>InputStream</code> inStream. The data     * is assumed to be in the specified encoding.     *     * @param inStream an <code>InputStream</code> containing the data     * @param encoding the encoding used for the data     * @return a <code>CertPath</code> initialized with the data from the     *   <code>InputStream</code>     * @exception CertificateException if an exception occurs while decoding or     *   the encoding requested is not supported     * @since 1.4     */    public CertPath engineGenerateCertPath(InputStream inStream,        String encoding) throws CertificateException    {        if (inStream == null) {            throw new CertificateException("Missing input stream");        }        try {            if (inStream.markSupported() == false) {                // consume the entire input stream                byte[] totalBytes;                totalBytes = getTotalBytes(new BufferedInputStream(inStream));                inStream = new ByteArrayInputStream(totalBytes);            }            // determine if binary or Base64 encoding. If Base64 encoding,            // each certificate must be bounded at the beginning by            // "-----BEGIN".            if (isBase64(inStream)) {                // Base64                byte[] data = base64_to_binary(inStream);                return new X509CertPath(new ByteArrayInputStream(data), encoding);            } else {                return(new X509CertPath(inStream, encoding));            }        } catch (IOException ioe) {            throw new CertificateException(ioe.getMessage());        }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?