/* * Copyright (C) 2014 The Android Open Source Project * Copyright (c) 1997, 2008, 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 javax.security.cert; import com.sun.security.cert.internal.x509.X509V1CertImpl; import java.io.InputStream; import java.lang.Class; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.Security; import java.math.BigInteger; import java.security.AccessController; import java.security.Principal; import java.security.PrivilegedAction; import java.security.PublicKey; import java.util.BitSet; import java.util.Date; /** * Abstract class for X.509 v1 certificates. This provides a standard * way to access all the version 1 attributes of an X.509 certificate. * Attributes that are specific to X.509 v2 or v3 are not available * through this interface. Future API evolution will provide full access to * complete X.509 v3 attributes. *
* The basic X.509 format was defined by * ISO/IEC and ANSI X9 and is described below in ASN.1: *
* Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING } **
* These certificates are widely used to support authentication and * other functionality in Internet security systems. Common applications * include Privacy Enhanced Mail (PEM), Transport Layer Security (SSL), * code signing for trusted software distribution, and Secure Electronic * Transactions (SET). *
* These certificates are managed and vouched for by Certificate * Authorities (CAs). CAs are services which create certificates by * placing data in the X.509 standard format and then digitally signing * that data. CAs act as trusted third parties, making introductions * between principals who have no direct knowledge of each other. * CA certificates are either signed by themselves, or by some other * CA such as a "root" CA. *
* The ASN.1 definition of {@code tbsCertificate} is: *
* TBSCertificate ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * serialNumber CertificateSerialNumber, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo, * } **
* Here is sample code to instantiate an X.509 certificate: *
* InputStream inStream = new FileInputStream("fileName-of-cert"); * X509Certificate cert = X509Certificate.getInstance(inStream); * inStream.close(); ** OR *
* byte[] certData = <certificate read from a file, say> * X509Certificate cert = X509Certificate.getInstance(certData); **
* In either case, the code that instantiates an X.509 certificate * consults the value of the {@code cert.provider.x509v1} security property * to locate the actual implementation or instantiates a default implementation. *
* The {@code cert.provider.x509v1} property is set to a default * implementation for X.509 such as: *
* cert.provider.x509v1=com.sun.security.cert.internal.x509.X509V1CertImpl **
* The value of this {@code cert.provider.x509v1} property has to be * changed to instantiate another implementation. If this security * property is not set, a default implementation will be used. * Currently, due to possible security restrictions on access to * Security properties, this value is looked up and cached at class * initialization time and will fallback on a default implementation if * the Security property is not accessible. * *
Note: The classes in the package {@code javax.security.cert} * exist for compatibility with earlier versions of the * Java Secure Sockets Extension (JSSE). New applications should instead * use the standard Java SE certificate classes located in * {@code java.security.cert}.
* * @author Hemma Prafullchandra * @since 1.4 * @see Certificate * @see java.security.cert.X509Extension * @see java.security.Security security properties */ public abstract class X509Certificate extends Certificate { /* * Constant to lookup in the Security properties file. * In the Security properties file the default implementation * for X.509 v3 is given as: ** cert.provider.x509v1=com.sun.security.cert.internal.x509.X509V1CertImpl **/ private static final String X509_PROVIDER = "cert.provider.x509v1"; private static String X509Provider; // Android-added. private static final String DEFAULT_X509_CERT_CLASS = X509V1CertImpl.class.getName(); static { X509Provider = AccessController.doPrivileged( new PrivilegedAction
Note: Only one DER-encoded * certificate is expected to be in the input stream. * Also, all X509Certificate * subclasses must provide a constructor of the form: *
{@code * public* * @param inStream an input stream with the data to be read to * initialize the certificate. * @return an X509Certificate object initialized with the data * from the input stream. * @exception CertificateException if a class initialization * or certificate parsing error occurs. */ public static final X509Certificate getInstance(InputStream inStream) throws CertificateException { return getInst((Object)inStream); } /** * Instantiates an X509Certificate object, and initializes it with * the specified byte array. * The implementation (X509Certificate is an abstract class) is * provided by the class specified as the value of the * {@code cert.provider.x509v1} security property. * *(InputStream inStream) ... * }
Note: All X509Certificate * subclasses must provide a constructor of the form: *
{@code * public* * @param certData a byte array containing the DER-encoded * certificate. * @return an X509Certificate object initialized with the data * from {@code certData}. * @exception CertificateException if a class initialization * or certificate parsing error occurs. */ public static final X509Certificate getInstance(byte[] certData) throws CertificateException { return getInst((Object)certData); } private static final X509Certificate getInst(Object value) throws CertificateException { /* * This turns out not to work for now. To run under JDK1.2 we would * need to call beginPrivileged() but we can't do that and run * under JDK1.1. */ String className = X509Provider; if (className == null || className.length() == 0) { // shouldn't happen, but assume corrupted properties file // provide access to sun implementation // // Android-changed. className = DEFAULT_X509_CERT_CLASS; } try { Class>[] params = null; if (value instanceof InputStream) { params = new Class>[] { InputStream.class }; } else if (value instanceof byte[]) { params = new Class>[] { value.getClass() }; } else throw new CertificateException("Unsupported argument type"); Class> certClass = Class.forName(className); // get the appropriate constructor and instantiate it Constructor> cons = certClass.getConstructor(params); // get a new instance Object obj = cons.newInstance(new Object[] {value}); return (X509Certificate)obj; } catch (ClassNotFoundException e) { throw new CertificateException("Could not find class: " + e); } catch (IllegalAccessException e) { throw new CertificateException("Could not access class: " + e); } catch (InstantiationException e) { throw new CertificateException("Problems instantiating: " + e); } catch (InvocationTargetException e) { throw new CertificateException("InvocationTargetException: " + e.getTargetException()); } catch (NoSuchMethodException e) { throw new CertificateException("Could not find class method: " + e.getMessage()); } } /** * Checks that the certificate is currently valid. It is if * the current date and time are within the validity period given in the * certificate. *(InputStream inStream) ... * }
* The validity period consists of two date/time values: * the first and last dates (and times) on which the certificate * is valid. It is defined in * ASN.1 as: *
* validity Validity * * Validity ::= SEQUENCE { * notBefore CertificateValidityDate, * notAfter CertificateValidityDate } * * CertificateValidityDate ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } ** * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public abstract void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException; /** * Checks that the specified date is within the certificate's * validity period. In other words, this determines whether the * certificate would be valid at the specified date/time. * * @param date the Date to check against to see if this certificate * is valid at that date/time. * @exception CertificateExpiredException if the certificate has expired * with respect to the {@code date} supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the {@code date} supplied. * @see #checkValidity() */ public abstract void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException; /** * Gets the {@code version} (version number) value from the * certificate. The ASN.1 definition for this is: *
* version [0] EXPLICIT Version DEFAULT v1 * * Version ::= INTEGER { v1(0), v2(1), v3(2) } ** * @return the version number from the ASN.1 encoding, i.e. 0, 1 or 2. */ public abstract int getVersion(); /** * Gets the {@code serialNumber} value from the certificate. * The serial number is an integer assigned by the certification * authority to each certificate. It must be unique for each * certificate issued by a given CA (i.e., the issuer name and * serial number identify a unique certificate). * The ASN.1 definition for this is: *
* serialNumber CertificateSerialNumber * * CertificateSerialNumber ::= INTEGER ** * @return the serial number. */ public abstract BigInteger getSerialNumber(); /** * Gets the {@code issuer} (issuer distinguished name) value from * the certificate. The issuer name identifies the entity that signed (and * issued) the certificate. * *
The issuer name field contains an * X.500 distinguished name (DN). * The ASN.1 definition for this is: *
* issuer Name * * Name ::= CHOICE { RDNSequence } * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * RelativeDistinguishedName ::= * SET OF AttributeValueAssertion * * AttributeValueAssertion ::= SEQUENCE { * AttributeType, * AttributeValue } * AttributeType ::= OBJECT IDENTIFIER * AttributeValue ::= ANY ** The {@code Name} describes a hierarchical name composed of * attributes, such as country name, and corresponding values, such as US. * The type of the {@code AttributeValue} component is determined by * the {@code AttributeType}; in general it will be a * {@code directoryString}. A {@code directoryString} is usually * one of {@code PrintableString}, * {@code TeletexString} or {@code UniversalString}. * * @return a Principal whose name is the issuer distinguished name. */ public abstract Principal getIssuerDN(); /** * Gets the {@code subject} (subject distinguished name) value * from the certificate. * The ASN.1 definition for this is: *
* subject Name ** *
See {@link #getIssuerDN() getIssuerDN} for {@code Name} * and other relevant definitions. * * @return a Principal whose name is the subject name. * @see #getIssuerDN() */ public abstract Principal getSubjectDN(); /** * Gets the {@code notBefore} date from the validity period of * the certificate. * The relevant ASN.1 definitions are: *
* validity Validity * * Validity ::= SEQUENCE { * notBefore CertificateValidityDate, * notAfter CertificateValidityDate } * * CertificateValidityDate ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } ** * @return the start date of the validity period. * @see #checkValidity() */ public abstract Date getNotBefore(); /** * Gets the {@code notAfter} date from the validity period of * the certificate. See {@link #getNotBefore() getNotBefore} * for relevant ASN.1 definitions. * * @return the end date of the validity period. * @see #checkValidity() */ public abstract Date getNotAfter(); /** * Gets the signature algorithm name for the certificate * signature algorithm. An example is the string "SHA-1/DSA". * The ASN.1 definition for this is: *
* signatureAlgorithm AlgorithmIdentifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * -- contains a value of the type * -- registered for use with the * -- algorithm object identifier value ** *
The algorithm name is determined from the {@code algorithm} * OID string. * * @return the signature algorithm name. */ public abstract String getSigAlgName(); /** * Gets the signature algorithm OID string from the certificate. * An OID is represented by a set of positive whole numbers separated * by periods. * For example, the string "1.2.840.10040.4.3" identifies the SHA-1 * with DSA signature algorithm, as per the PKIX part I. * *
See {@link #getSigAlgName() getSigAlgName} for * relevant ASN.1 definitions. * * @return the signature algorithm OID string. */ public abstract String getSigAlgOID(); /** * Gets the DER-encoded signature algorithm parameters from this * certificate's signature algorithm. In most cases, the signature * algorithm parameters are null; the parameters are usually * supplied with the certificate's public key. * *
See {@link #getSigAlgName() getSigAlgName} for * relevant ASN.1 definitions. * * @return the DER-encoded signature algorithm parameters, or * null if no parameters are present. */ public abstract byte[] getSigAlgParams(); }