151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
26f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.x509;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.OutputStream;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.math.BigInteger;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.*;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.*;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.cert.Certificate;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*;
35d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Rootimport java.util.concurrent.ConcurrentHashMap;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport javax.security.auth.x500.X500Principal;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.misc.HexDumpEncoder;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.util.*;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.security.provider.X509Factory;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The X509CertImpl class represents an X.509 certificate. These certificates
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are widely used to support authentication and other functionality in
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Internet security systems.  Common applications include Privacy Enhanced
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Mail (PEM), Transport Layer Security (SSL), code signing for trusted
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * software distribution, and Secure Electronic Transactions (SET).  There
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is a commercial infrastructure ready to manage large scale deployments
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of X.509 identity certificates.
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>These certificates are managed and vouched for by <em>Certificate
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Authorities</em> (CAs).  CAs are services which create certificates by
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * placing data in the X.509 standard format and then digitally signing
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that data.  Such signatures are quite difficult to forge.  CAs act as
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * trusted third parties, making introductions between agents who have no
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * direct knowledge of each other.  CA certificates are either signed by
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * themselves, or by some other CA such as a "root" CA.
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>RFC 1422 is very informative, though it does not describe much
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the recent work being done with X.509 certificates.  That includes
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a 1996 version (X.509v3) and a variety of enhancements being made to
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * facilitate an explosion of personal certificates used as "Internet
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Drivers' Licences", or with SET for credit card transactions.
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>More recent work includes the IETF PKIX Working Group efforts,
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * especially RFC2459.
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Dave Brownell
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Amit Kapoor
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Hemma Prafullchandra
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see X509CertInfo
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class X509CertImpl extends X509Certificate implements DerEncoder {
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final long serialVersionUID = -3457612960190864406L;
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String DOT = ".";
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Public attribute names.
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String NAME = "x509";
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String INFO = X509CertInfo.NAME;
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String ALG_ID = "algorithm";
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SIGNATURE = "signature";
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SIGNED_CERT = "signed_cert";
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The following are defined for ease-of-use. These
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * are the most frequently retrieved attributes.
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.info.subject.dname
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SUBJECT_DN = NAME + DOT + INFO + DOT +
93d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                               X509CertInfo.SUBJECT + DOT + X509CertInfo.DN_NAME;
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.info.issuer.dname
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String ISSUER_DN = NAME + DOT + INFO + DOT +
96d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                               X509CertInfo.ISSUER + DOT + X509CertInfo.DN_NAME;
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.info.serialNumber.number
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SERIAL_ID = NAME + DOT + INFO + DOT +
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               X509CertInfo.SERIAL_NUMBER + DOT +
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               CertificateSerialNumber.NUMBER;
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.info.key.value
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT +
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               X509CertInfo.KEY + DOT +
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               CertificateX509Key.KEY;
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.info.version.value
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String VERSION = NAME + DOT + INFO + DOT +
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               X509CertInfo.VERSION + DOT +
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               CertificateVersion.VERSION;
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.algorithm
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SIG_ALG = NAME + DOT + ALG_ID;
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // x509.signature
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final String SIG = NAME + DOT + SIGNATURE;
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // when we sign and decode we set this to true
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // this is our means to make certificates immutable
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean readOnly = false;
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Certificate data, and its envelope
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private byte[]              signedCert = null;
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected X509CertInfo      info = null;
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected AlgorithmId       algId = null;
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected byte[]            signature = null;
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // recognized extension OIDS
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String KEY_USAGE_OID = "2.5.29.15";
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String BASIC_CONSTRAINT_OID = "2.5.29.19";
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String SUBJECT_ALT_NAME_OID = "2.5.29.17";
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String ISSUER_ALT_NAME_OID = "2.5.29.18";
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String AUTH_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.1";
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // number of standard key usage bits.
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int NUM_STANDARD_KEY_USAGE = 9;
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // SubjectAlterntativeNames cache
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Collection<List<?>> subjectAlternativeNames;
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // IssuerAlternativeNames cache
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Collection<List<?>> issuerAlternativeNames;
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // ExtendedKeyUsage cache
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private List<String> extKeyUsage;
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // AuthorityInformationAccess cache
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Set<AccessDescription> authInfoAccess;
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * PublicKey that has previously been used to verify
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the signature of this certificate. Null if the certificate has not
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * yet been verified.
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private PublicKey verifiedPublicKey;
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If verifiedPublicKey is not null, name of the provider used to
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * successfully verify the signature of this certificate, or the
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * empty String if no provider was explicitly specified.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String verifiedProvider;
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If verifiedPublicKey is not null, result of the verification using
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * verifiedPublicKey and verifiedProvider. If true, verification was
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * successful, if false, it failed.
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean verificationResult;
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Default constructor.
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X509CertImpl() { }
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Unmarshals a certificate from its encoded form, parsing the
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * encoded bytes.  This form of constructor is used by agents which
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * need to examine and use certificate contents.  That is, this is
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * one of the more commonly used constructors.  Note that the buffer
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * must include only a certificate, and no "garbage" may be left at
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the end.  If you need to ignore data at the end of a certificate,
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * use another constructor.
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param certData the encoded bytes, with no trailing padding.
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on parsing and initialization errors.
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X509CertImpl(byte[] certData) throws CertificateException {
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            parse(new DerValue(certData));
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException e) {
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signedCert = null;
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Unable to initialize, " + e, e);
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1956975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer    // BEGIN Android-removed
1966975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer    /*
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unmarshals an X.509 certificate from an input stream.  If the
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate is RFC1421 hex-encoded, then it must begin with
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the line X509Factory.BEGIN_CERT and end with the line
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Factory.END_CERT.
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param in an input stream holding at least one certificate that may
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        be either DER-encoded or RFC1421 hex-encoded version of the
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        DER-encoded certificate.
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on parsing and initialization errors.
2077b5c7bb3e2ac90c7622a1ce42d4a7d149cc63ad9Sergio Giro     *
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X509CertImpl(InputStream in) throws CertificateException {
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerValue der = null;
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BufferedInputStream inBuffered = new BufferedInputStream(in);
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // First try reading stream as HEX-encoded DER-encoded bytes,
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // since not mistakable for raw DER
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            inBuffered.mark(Integer.MAX_VALUE);
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            der = readRFC1421Cert(inBuffered);
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Next, try reading stream as raw DER-encoded bytes
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                inBuffered.reset();
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                der = new DerValue(inBuffered);
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException ioe1) {
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new CertificateException("Input stream must be " +
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                               "either DER-encoded bytes " +
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                               "or RFC1421 hex-encoded " +
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                               "DER-encoded bytes: " +
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                               ioe1.getMessage(), ioe1);
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            parse(der);
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signedCert = null;
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Unable to parse DER value of " +
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                           "certificate, " + ioe, ioe);
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * read input stream as HEX-encoded DER-encoded bytes
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param in InputStream to read
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @returns DerValue corresponding to decoded HEX-encoded bytes
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws IOException if stream can not be interpreted as RFC1421
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                     encoded bytes
2487b5c7bb3e2ac90c7622a1ce42d4a7d149cc63ad9Sergio Giro     *
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private DerValue readRFC1421Cert(InputStream in) throws IOException {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerValue der = null;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String line = null;
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BufferedReader certBufferedReader =
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            new BufferedReader(new InputStreamReader(in, "ASCII"));
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            line = certBufferedReader.readLine();
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe1) {
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Unable to read InputStream: " +
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                  ioe1.getMessage());
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (line.equals(X509Factory.BEGIN_CERT)) {
2617b5c7bb3e2ac90c7622a1ce42d4a7d149cc63ad9Sergio Giro            /* stream appears to be hex-encoded bytes *
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ByteArrayOutputStream decstream = new ByteArrayOutputStream();
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while ((line = certBufferedReader.readLine()) != null) {
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (line.equals(X509Factory.END_CERT)) {
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        der = new DerValue(decstream.toByteArray());
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
269cf4cc555d38c0771e88b7a3945a51d6492bcad47Sergio Giro                        decstream.write(Base64.getMimeDecoder().decode(line));
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException ioe2) {
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IOException("Unable to read InputStream: "
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                      + ioe2.getMessage());
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("InputStream is not RFC1421 hex-encoded " +
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                  "DER bytes");
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return der;
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
2826975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer    */
2836975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer    // END Android-removed
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Construct an initialized X509 Certificate. The certificate is stored
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in raw form and has to be signed to be useful.
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @params info the X509CertificateInfo which the Certificate is to be
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *              created from.
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X509CertImpl(X509CertInfo certInfo) {
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.info = certInfo;
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Unmarshal a certificate from its encoded form, parsing a DER value.
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This form of constructor is used by agents which need to examine
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and use certificate contents.
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param derVal the der value containing the encoded cert.
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on parsing and initialization errors.
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X509CertImpl(DerValue derVal) throws CertificateException {
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            parse(derVal);
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException e) {
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signedCert = null;
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Unable to initialize, " + e, e);
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
314b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * Unmarshal a certificate from its encoded form, parsing a DER value.
315b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * This form of constructor is used by agents which need to examine
316b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * and use certificate contents.
317b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *
318b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * @param derVal the der value containing the encoded cert.
319b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * @exception CertificateException on parsing and initialization errors.
320b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     */
321b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    public X509CertImpl(DerValue derVal, byte[] encoded)
322b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        throws CertificateException {
323b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        try {
324b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            parse(derVal, encoded);
325b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        } catch (IOException e) {
326b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            signedCert = null;
327b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            throw new CertificateException("Unable to initialize, " + e, e);
328b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        }
329b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    }
330b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin
331b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    /**
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Appends the certificate to an output stream.
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param out an input stream to which the certificate is appended.
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateEncodingException on encoding errors.
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void encode(OutputStream out)
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateEncodingException {
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signedCert == null)
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException(
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          "Null certificate to encode");
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            out.write(signedCert.clone());
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException e) {
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException(e.toString());
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * DER encode this object onto an output stream.
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Implements the <code>DerEncoder</code> interface.
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param out the output stream on which to write the DER encoding.
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException on encoding error.
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void derEncode(OutputStream out) throws IOException {
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signedCert == null)
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Null certificate to encode");
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        out.write(signedCert.clone());
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the encoded form of this certificate. It is
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * assumed that each certificate type would have only a single
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * form of encoding; for example, X.509 certificates would
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be encoded as ASN.1 DER.
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateEncodingException if an encoding error occurs.
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getEncoded() throws CertificateEncodingException {
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getEncodedInternal().clone();
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returned the encoding as an uncloned byte array. Callers must
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * guarantee that they neither modify it nor expose it to untrusted
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * code.
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getEncodedInternal() throws CertificateEncodingException {
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signedCert == null) {
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException(
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          "Null certificate to encode");
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return signedCert;
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Throws an exception if the certificate was not signed using the
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * verification key provided.  Successfully verifying a certificate
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * does <em>not</em> indicate that one should trust the entity which
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * it represents.
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the public key used for verification.
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception InvalidKeyException on incorrect key.
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchAlgorithmException on unsupported signature
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algorithms.
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchProviderException if there's no default provider.
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception SignatureException on signature errors.
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on encoding errors.
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void verify(PublicKey key)
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, NoSuchAlgorithmException,
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        InvalidKeyException, NoSuchProviderException, SignatureException {
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verify(key, "");
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Throws an exception if the certificate was not signed using the
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * verification key provided.  Successfully verifying a certificate
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * does <em>not</em> indicate that one should trust the entity which
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * it represents.
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the public key used for verification.
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param sigProvider the name of the provider.
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchAlgorithmException on unsupported signature
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algorithms.
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception InvalidKeyException on incorrect key.
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchProviderException on incorrect provider.
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception SignatureException on signature errors.
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on encoding errors.
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void verify(PublicKey key, String sigProvider)
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws CertificateException, NoSuchAlgorithmException,
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InvalidKeyException, NoSuchProviderException, SignatureException {
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sigProvider == null) {
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sigProvider = "";
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((verifiedPublicKey != null) && verifiedPublicKey.equals(key)) {
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // this certificate has already been verified using
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // this public key. Make sure providers match, too.
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (sigProvider.equals(verifiedProvider)) {
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (verificationResult) {
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new SignatureException("Signature does not match.");
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signedCert == null) {
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException("Uninitialized certificate");
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Verify the signature ...
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Signature sigVerf = null;
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sigProvider.length() == 0) {
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sigVerf = Signature.getInstance(algId.getName());
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sigVerf = Signature.getInstance(algId.getName(), sigProvider);
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sigVerf.initVerify(key);
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] rawCert = info.getEncodedInfo();
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sigVerf.update(rawCert, 0, rawCert.length);
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // verify may throw SignatureException for invalid encodings, etc.
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verificationResult = sigVerf.verify(signature);
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verifiedPublicKey = key;
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        verifiedProvider = sigProvider;
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (verificationResult == false) {
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new SignatureException("Signature does not match.");
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
4696f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * Throws an exception if the certificate was not signed using the
4706f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * verification key provided.  This method uses the signature verification
4716f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * engine supplied by the specified provider. Note that the specified
4726f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * Provider object does not have to be registered in the provider list.
4736f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * Successfully verifying a certificate does <em>not</em> indicate that one
4746f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * should trust the entity which it represents.
4756f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     *
4766f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @param key the public key used for verification.
4776f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @param sigProvider the provider.
4786f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     *
4796f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @exception NoSuchAlgorithmException on unsupported signature
4806f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * algorithms.
4816f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @exception InvalidKeyException on incorrect key.
4826f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @exception SignatureException on signature errors.
4836f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * @exception CertificateException on encoding errors.
4846f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     */
4856f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root    public synchronized void verify(PublicKey key, Provider sigProvider)
4866f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            throws CertificateException, NoSuchAlgorithmException,
4876f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            InvalidKeyException, SignatureException {
4886f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        if (signedCert == null) {
4896f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            throw new CertificateEncodingException("Uninitialized certificate");
4906f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        }
4916f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        // Verify the signature ...
4926f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        Signature sigVerf = null;
4936f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        if (sigProvider == null) {
4946f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            sigVerf = Signature.getInstance(algId.getName());
4956f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        } else {
4966f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            sigVerf = Signature.getInstance(algId.getName(), sigProvider);
4976f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        }
4986f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        sigVerf.initVerify(key);
4996f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root
5006f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        byte[] rawCert = info.getEncodedInfo();
5016f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        sigVerf.update(rawCert, 0, rawCert.length);
5026f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root
5036f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        // verify may throw SignatureException for invalid encodings, etc.
5046f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        verificationResult = sigVerf.verify(signature);
5056f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        verifiedPublicKey = key;
5066f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root
5076f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        if (verificationResult == false) {
5086f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            throw new SignatureException("Signature does not match.");
5096f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        }
5106f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root    }
5116f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root
5126f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     /**
5136f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * This static method is the default implementation of the
5146f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * verify(PublicKey key, Provider sigProvider) method in X509Certificate.
5156f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * Called from java.security.cert.X509Certificate.verify(PublicKey key,
5166f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     * Provider sigProvider)
5176f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root     */
5186f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root    public static void verify(X509Certificate cert, PublicKey key,
5196f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            Provider sigProvider) throws CertificateException,
5206f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root            NoSuchAlgorithmException, InvalidKeyException, SignatureException {
5216f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root        cert.verify(key, sigProvider);
5226f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root    }
5236f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root
5246f31965522c21a5c47296b31d67cc07cb3c65748Kenny Root    /**
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an X.509 certificate, and signs it using the given key
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (associating a signature algorithm and an X.500 name).
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This operation is used to implement the certificate generation
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * functionality of a certificate authority.
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the private key used for signing.
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param algorithm the name of the signature algorithm used.
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception InvalidKeyException on incorrect key.
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchAlgorithmException on unsupported signature
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algorithms.
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchProviderException if there's no default provider.
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception SignatureException on signature errors.
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on encoding errors.
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void sign(PrivateKey key, String algorithm)
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, NoSuchAlgorithmException,
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        InvalidKeyException, NoSuchProviderException, SignatureException {
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sign(key, algorithm, null);
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates an X.509 certificate, and signs it using the given key
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (associating a signature algorithm and an X.500 name).
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This operation is used to implement the certificate generation
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * functionality of a certificate authority.
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param key the private key used for signing.
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param algorithm the name of the signature algorithm used.
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param provider the name of the provider.
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchAlgorithmException on unsupported signature
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * algorithms.
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception InvalidKeyException on incorrect key.
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NoSuchProviderException on incorrect provider.
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception SignatureException on signature errors.
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on encoding errors.
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void sign(PrivateKey key, String algorithm, String provider)
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, NoSuchAlgorithmException,
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        InvalidKeyException, NoSuchProviderException, SignatureException {
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (readOnly)
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new CertificateEncodingException(
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              "cannot over-write existing certificate");
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Signature sigEngine = null;
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((provider == null) || (provider.length() == 0))
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sigEngine = Signature.getInstance(algorithm);
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                sigEngine = Signature.getInstance(algorithm, provider);
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sigEngine.initSign(key);
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                // in case the name is reset
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            algId = AlgorithmId.get(sigEngine.getAlgorithm());
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerOutputStream out = new DerOutputStream();
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerOutputStream tmp = new DerOutputStream();
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // encode certificate info
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            info.encode(tmp);
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] rawCert = tmp.toByteArray();
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // encode algorithm identifier
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            algId.encode(tmp);
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Create and encode the signature itself.
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sigEngine.update(rawCert, 0, rawCert.length);
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signature = sigEngine.sign();
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            tmp.putBitString(signature);
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Wrap the signed data in a SEQUENCE { data, algorithm, sig }
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            out.write(DerValue.tag_Sequence, tmp);
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signedCert = out.toByteArray();
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            readOnly = true;
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException e) {
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException(e.toString());
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      }
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Checks that the certificate is currently valid, i.e. the current
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * time is within the specified validity period.
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateExpiredException if the certificate has expired.
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateNotYetValidException if the certificate is not
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * yet valid.
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void checkValidity()
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateExpiredException, CertificateNotYetValidException {
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date date = new Date();
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkValidity(date);
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Checks that the specified date is within the certificate's
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * validity period, or basically if the certificate would be
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * valid at the specified date/time.
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param date the Date to check against to see if this certificate
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        is valid at that date/time.
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateExpiredException if the certificate has expired
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * with respect to the <code>date</code> supplied.
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateNotYetValidException if the certificate is not
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * yet valid with respect to the <code>date</code> supplied.
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void checkValidity(Date date)
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateExpiredException, CertificateNotYetValidException {
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CertificateValidity interval = null;
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            interval = (CertificateValidity)info.get(CertificateValidity.NAME);
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateNotYetValidException("Incorrect validity period");
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (interval == null)
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateNotYetValidException("Null validity period");
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        interval.valid(date);
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return the requested attribute from the certificate.
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Note that the X509CertInfo is not cloned for performance reasons.
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Callers must ensure that they do not modify it. All other
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * attributes are cloned.
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name the name of the attribute.
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateParsingException on invalid attribute identifier.
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Object get(String name)
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateParsingException {
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        X509AttributeName attr = new X509AttributeName(name);
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String id = attr.getPrefix();
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(id.equalsIgnoreCase(NAME))) {
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("Invalid root of "
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          + "attribute name, expected [" + NAME +
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          "], received " + "[" + id + "]");
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        attr = new X509AttributeName(attr.getSuffix());
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        id = attr.getPrefix();
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (id.equalsIgnoreCase(INFO)) {
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (info == null) {
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (attr.getSuffix() != null) {
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return info.get(attr.getSuffix());
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (IOException e) {
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new CertificateParsingException(e.toString());
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (CertificateException e) {
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new CertificateParsingException(e.toString());
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return info;
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(ALG_ID)) {
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return(algId);
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(SIGNATURE)) {
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (signature != null)
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return signature.clone();
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (signedCert != null)
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return signedCert.clone();
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("Attribute name not "
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 + "recognized or get() not allowed for the same: " + id);
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Set the requested attribute in the certificate.
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name the name of the attribute.
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param obj the value of the attribute.
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on invalid attribute identifier.
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException on encoding error of attribute.
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void set(String name, Object obj)
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, IOException {
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // check if immutable
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly)
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("cannot over-write existing"
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                           + " certificate");
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        X509AttributeName attr = new X509AttributeName(name);
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String id = attr.getPrefix();
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(id.equalsIgnoreCase(NAME))) {
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Invalid root of attribute name,"
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           + " expected [" + NAME + "], received " + id);
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        attr = new X509AttributeName(attr.getSuffix());
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        id = attr.getPrefix();
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (id.equalsIgnoreCase(INFO)) {
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (attr.getSuffix() == null) {
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!(obj instanceof X509CertInfo)) {
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new CertificateException("Attribute value should"
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    + " be of type X509CertInfo.");
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                info = (X509CertInfo)obj;
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                signedCert = null;  //reset this as certificate data has changed
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                info.set(attr.getSuffix(), obj);
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                signedCert = null;  //reset this as certificate data has changed
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Attribute name not recognized or " +
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              "set() not allowed for the same: " + id);
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Delete the requested attribute from the certificate.
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name the name of the attribute.
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateException on invalid attribute identifier.
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IOException on other errors.
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void delete(String name)
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, IOException {
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // check if immutable
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly)
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("cannot over-write existing"
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                           + " certificate");
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        X509AttributeName attr = new X509AttributeName(name);
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String id = attr.getPrefix();
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(id.equalsIgnoreCase(NAME))) {
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Invalid root of attribute name,"
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   + " expected ["
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   + NAME + "], received " + id);
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        attr = new X509AttributeName(attr.getSuffix());
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        id = attr.getPrefix();
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (id.equalsIgnoreCase(INFO)) {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (attr.getSuffix() != null) {
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                info = null;
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                info.delete(attr.getSuffix());
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(ALG_ID)) {
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            algId = null;
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(SIGNATURE)) {
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signature = null;
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (id.equalsIgnoreCase(SIGNED_CERT)) {
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            signedCert = null;
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Attribute name not recognized or " +
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              "delete() not allowed for the same: " + id);
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return an enumeration of names of attributes existing within this
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * attribute.
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Enumeration<String> getElements() {
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        AttributeNameEnumeration elements = new AttributeNameEnumeration();
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        elements.addElement(NAME + DOT + INFO);
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        elements.addElement(NAME + DOT + ALG_ID);
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        elements.addElement(NAME + DOT + SIGNATURE);
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        elements.addElement(NAME + DOT + SIGNED_CERT);
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return elements.elements();
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return the name of this attribute.
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getName() {
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return(NAME);
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a printable representation of the certificate.  This does not
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * contain all the information available to distinguish this from any
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * other certificate.  The certificate must be fully constructed
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * before this function may be called.
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toString() {
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null || algId == null || signature == null)
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return "";
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        StringBuilder sb = new StringBuilder();
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sb.append("[\n");
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sb.append(info.toString() + "\n");
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sb.append("  Algorithm: [" + algId.toString() + "]\n");
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        HexDumpEncoder encoder = new HexDumpEncoder();
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sb.append("  Signature:\n" + encoder.encodeBuffer(signature));
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sb.append("\n]");
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return sb.toString();
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the strongly typed gets, as per java.security.cert.X509Certificate
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the publickey from this certificate.
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the publickey.
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PublicKey getPublicKey() {
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            PublicKey key = (PublicKey)info.get(CertificateX509Key.NAME
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                + DOT + CertificateX509Key.KEY);
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return key;
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the version number from the certificate.
85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the version number, i.e. 1, 2 or 3.
85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getVersion() {
85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int vers = ((Integer)info.get(CertificateVersion.NAME
85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        + DOT + CertificateVersion.VERSION)).intValue();
86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return vers+1;
86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the serial number from the certificate.
86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the serial number.
87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public BigInteger getSerialNumber() {
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SerialNumber ser = getSerialNumberObject();
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ser != null ? ser.getNumber() : null;
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the serial number from the certificate as
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * a SerialNumber object.
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the serial number.
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SerialNumber getSerialNumberObject() {
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SerialNumber ser = (SerialNumber)info.get(
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              CertificateSerialNumber.NAME + DOT +
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                              CertificateSerialNumber.NUMBER);
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           return ser;
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the subject distinguished name from the certificate.
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the subject name.
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Principal getSubjectDN() {
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
906d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            Principal subject = (Principal)info.get(X509CertInfo.SUBJECT + DOT +
907d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                                    X509CertInfo.DN_NAME);
90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return subject;
90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get subject name as X500Principal. Overrides implementation in
91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Certificate with a slightly more efficient version that is
91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * also aware of X509CertImpl mutability.
91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X500Principal getSubjectX500Principal() {
92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            X500Principal subject = (X500Principal)info.get(
925d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                            X509CertInfo.SUBJECT + DOT +
926d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                            "x500principal");
92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return subject;
92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the issuer distinguished name from the certificate.
93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the issuer name.
93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Principal getIssuerDN() {
93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
942d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            Principal issuer = (Principal)info.get(X509CertInfo.ISSUER + DOT +
943d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                                   X509CertInfo.DN_NAME);
94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return issuer;
94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get issuer name as X500Principal. Overrides implementation in
95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Certificate with a slightly more efficient version that is
95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * also aware of X509CertImpl mutability.
95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public X500Principal getIssuerX500Principal() {
95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            X500Principal issuer = (X500Principal)info.get(
961d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                            X509CertInfo.ISSUER + DOT +
962d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                            "x500principal");
96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return issuer;
96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the notBefore date from the validity period of the certificate.
97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the start date of the validity period.
97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Date getNotBefore() {
97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Date d = (Date) info.get(CertificateValidity.NAME + DOT +
97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        CertificateValidity.NOT_BEFORE);
98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return d;
98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the notAfter date from the validity period of the certificate.
98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the end date of the validity period.
99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Date getNotAfter() {
99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Date d = (Date) info.get(CertificateValidity.NAME + DOT +
99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     CertificateValidity.NOT_AFTER);
99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return d;
99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the DER encoded certificate informations, the
100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>tbsCertificate</code> from this certificate.
100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This can be used to verify the signature independently.
100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the DER encoded certificate information.
100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception CertificateEncodingException if an encoding error occurs.
101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getTBSCertificate() throws CertificateEncodingException {
101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info != null) {
101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return info.getEncodedInfo();
101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else
101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateEncodingException("Uninitialized certificate");
101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
101951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the raw Signature bits from the certificate.
102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the signature.
102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getSignature() {
102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (signature == null)
102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] dup = new byte[signature.length];
102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        System.arraycopy(signature, 0, dup, 0, dup.length);
102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return dup;
102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the signature algorithm name for the certificate
103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * signature algorithm.
103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For example, the string "SHA-1/DSA" or "DSS".
103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the signature algorithm name.
103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getSigAlgName() {
103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (algId == null)
104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (algId.getName());
104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the signature algorithm OID string from the certificate.
104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For example, the string "1.2.840.10040.4.3"
104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the signature algorithm oid string.
104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String getSigAlgOID() {
105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (algId == null)
105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ObjectIdentifier oid = algId.getOID();
105451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (oid.toString());
105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the DER encoded signature algorithm parameters from this
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate's signature algorithm.
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the DER encoded signature algorithm parameters, or
106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         null if no parameters are present.
106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getSigAlgParams() {
106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (algId == null)
106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return algId.getEncodedParams();
106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException e) {
107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the Issuer Unique Identity from the certificate.
107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the Issuer Unique Identity.
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean[] getIssuerUniqueID() {
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            UniqueIdentity id = (UniqueIdentity)info.get(
1084d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                 X509CertInfo.ISSUER_ID);
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (id == null)
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (id.getId());
108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the Subject Unique Identity from the certificate.
109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the Subject Unique Identity.
109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean[] getSubjectUniqueID() {
110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            UniqueIdentity id = (UniqueIdentity)info.get(
1104d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                                 X509CertInfo.SUBJECT_ID);
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (id == null)
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return (id.getId());
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1114d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    public KeyIdentifier getAuthKeyId() {
1115d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        AuthorityKeyIdentifierExtension aki
1116d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            = getAuthorityKeyIdentifierExtension();
1117d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        if (aki != null) {
1118d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            try {
1119d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                return (KeyIdentifier)aki.get(
1120d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                    AuthorityKeyIdentifierExtension.KEY_ID);
1121d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            } catch (IOException ioe) {} // not possible
1122d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        }
1123d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        return null;
1124d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    }
1125d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
1126d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    /**
1127d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     * Returns the subject's key identifier, or null
1128d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     */
1129d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    public KeyIdentifier getSubjectKeyId() {
1130d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        SubjectKeyIdentifierExtension ski = getSubjectKeyIdentifierExtension();
1131d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        if (ski != null) {
1132d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            try {
1133d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                return (KeyIdentifier)ski.get(
1134d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                    SubjectKeyIdentifierExtension.KEY_ID);
1135d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            } catch (IOException ioe) {} // not possible
1136d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        }
1137d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        return null;
1138d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    }
1139d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get AuthorityKeyIdentifier extension
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return AuthorityKeyIdentifier object or null (if no such object
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in certificate)
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public AuthorityKeyIdentifierExtension getAuthorityKeyIdentifierExtension()
114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (AuthorityKeyIdentifierExtension)
114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.AuthorityKey_Id);
114951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get BasicConstraints extension
115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return BasicConstraints object or null (if no such object in
115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public BasicConstraintsExtension getBasicConstraintsExtension() {
115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (BasicConstraintsExtension)
115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.BasicConstraints_Id);
115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get CertificatePoliciesExtension
116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return CertificatePoliciesExtension or null (if no such object in
116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CertificatePoliciesExtension getCertificatePoliciesExtension() {
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (CertificatePoliciesExtension)
116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.CertificatePolicies_Id);
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get ExtendedKeyUsage extension
117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return ExtendedKeyUsage extension object or null (if no such object
117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in certificate)
117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public ExtendedKeyUsageExtension getExtendedKeyUsageExtension() {
117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (ExtendedKeyUsageExtension)
117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.ExtendedKeyUsage_Id);
117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get IssuerAlternativeName extension
118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return IssuerAlternativeName object or null (if no such object in
118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public IssuerAlternativeNameExtension getIssuerAlternativeNameExtension() {
118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (IssuerAlternativeNameExtension)
118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.IssuerAlternativeName_Id);
118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get NameConstraints extension
119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return NameConstraints object or null (if no such object in certificate)
119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public NameConstraintsExtension getNameConstraintsExtension() {
119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (NameConstraintsExtension)
119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.NameConstraints_Id);
119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get PolicyConstraints extension
120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return PolicyConstraints object or null (if no such object in
120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PolicyConstraintsExtension getPolicyConstraintsExtension() {
120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (PolicyConstraintsExtension)
120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.PolicyConstraints_Id);
120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get PolicyMappingsExtension extension
121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return PolicyMappingsExtension object or null (if no such object
121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * in certificate)
121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PolicyMappingsExtension getPolicyMappingsExtension() {
121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (PolicyMappingsExtension)
121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.PolicyMappings_Id);
121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get PrivateKeyUsage extension
122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return PrivateKeyUsage object or null (if no such object in certificate)
122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PrivateKeyUsageExtension getPrivateKeyUsageExtension() {
122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (PrivateKeyUsageExtension)
122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.PrivateKeyUsage_Id);
122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get SubjectAlternativeName extension
123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return SubjectAlternativeName object or null (if no such object in
123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SubjectAlternativeNameExtension getSubjectAlternativeNameExtension()
123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (SubjectAlternativeNameExtension)
123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.SubjectAlternativeName_Id);
123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get SubjectKeyIdentifier extension
124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return SubjectKeyIdentifier object or null (if no such object in
124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SubjectKeyIdentifierExtension getSubjectKeyIdentifierExtension() {
124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (SubjectKeyIdentifierExtension)
124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.SubjectKey_Id);
124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get CRLDistributionPoints extension
125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return CRLDistributionPoints object or null (if no such object in
125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate)
125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public CRLDistributionPointsExtension getCRLDistributionPointsExtension() {
125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (CRLDistributionPointsExtension)
125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.CRLDistributionPoints_Id);
125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Return true if a critical extension is found that is
126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not supported, otherwise return false.
126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean hasUnsupportedCriticalExtension() {
126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null)
126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions exts = (CertificateExtensions)info.get(
126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                         CertificateExtensions.NAME);
127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (exts == null)
127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return exts.hasUnsupportedCriticalExtension();
127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets a Set of the extension(s) marked CRITICAL in the
128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate. In the returned set, each extension is
128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * represented by its OID string.
128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a set of the extension oid strings in the
128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate that are marked critical.
128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Set<String> getCriticalExtensionOIDs() {
128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions exts = (CertificateExtensions)info.get(
129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                         CertificateExtensions.NAME);
129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (exts == null) {
129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Set<String> extSet = new TreeSet<>();
129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (Extension ex : exts.getAllExtensions()) {
129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (ex.isCritical()) {
129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    extSet.add(ex.getExtensionId().toString());
130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return extSet;
130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets a Set of the extension(s) marked NON-CRITICAL in the
131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate. In the returned set, each extension is
131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * represented by its OID string.
131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a set of the extension oid strings in the
131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * certificate that are NOT marked critical.
131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Set<String> getNonCriticalExtensionOIDs() {
131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions exts = (CertificateExtensions)info.get(
132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                         CertificateExtensions.NAME);
132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (exts == null) {
132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Set<String> extSet = new TreeSet<>();
132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (Extension ex : exts.getAllExtensions()) {
132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!ex.isCritical()) {
132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    extSet.add(ex.getExtensionId().toString());
133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            extSet.addAll(exts.getUnparseableExtensions().keySet());
133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return extSet;
133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the extension identified by the given ObjectIdentifier
134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param oid the Object Identifier value for the extension.
134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return Extension or null if certificate does not contain this
134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         extension
134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Extension getExtension(ObjectIdentifier oid) {
134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions extensions;
135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME);
135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (CertificateException ce) {
135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extensions == null) {
135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Extension ex = extensions.getExtension(oid.toString());
136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (ex != null) {
136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return ex;
136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (Extension ex2: extensions.getAllExtensions()) {
136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (ex2.getExtensionId().equals((Object)oid)) {
136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        //XXXX May want to consider cloning this
136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return ex2;
136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* no such extension in this certificate */
137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Extension getUnparseableExtension(ObjectIdentifier oid) {
137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (info == null) {
138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions extensions;
138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                extensions = (CertificateExtensions)info.get(CertificateExtensions.NAME);
138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (CertificateException ce) {
138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extensions == null) {
139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return extensions.getUnparseableExtensions().get(oid.toString());
139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets the DER encoded extension identified by the given
140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * oid String.
140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param oid the Object Identifier value for the extension.
140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public byte[] getExtensionValue(String oid) {
140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ObjectIdentifier findOID = new ObjectIdentifier(oid);
140851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String extAlias = OIDMap.getName(findOID);
140951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Extension certExt = null;
141051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CertificateExtensions exts = (CertificateExtensions)info.get(
141151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     CertificateExtensions.NAME);
141251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
141351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extAlias == null) { // may be unknown
141451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // get the extensions, search thru' for this oid
141551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (exts == null) {
141651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return null;
141751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
141851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
141951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (Extension ex : exts.getAllExtensions()) {
142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ObjectIdentifier inCertOID = ex.getExtensionId();
142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (inCertOID.equals((Object)findOID)) {
142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        certExt = ex;
142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else { // there's sub-class that can handle this extension
142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    certExt = (Extension)this.get(extAlias);
142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (CertificateException e) {
143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // get() throws an Exception instead of returning null, ignore
143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (certExt == null) {
143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (exts != null) {
143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    certExt = exts.getUnparseableExtensions().get(oid);
143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (certExt == null) {
143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return null;
143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] extData = certExt.getExtensionValue();
144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extData == null) {
144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerOutputStream out = new DerOutputStream();
144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            out.putOctetString(extData);
144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return out.toByteArray();
144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get a boolean array representing the bits of the KeyUsage extension,
145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (oid = 2.5.29.15).
145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the bit values of this extension as an array of booleans.
145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean[] getKeyUsage() {
145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String extAlias = OIDMap.getName(PKIXExtensions.KeyUsage_Id);
146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extAlias == null)
146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            KeyUsageExtension certExt = (KeyUsageExtension)this.get(extAlias);
146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (certExt == null)
146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean[] ret = certExt.getBits();
146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ret.length < NUM_STANDARD_KEY_USAGE) {
147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                boolean[] usageBits = new boolean[NUM_STANDARD_KEY_USAGE];
147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                System.arraycopy(ret, 0, usageBits, 0, ret.length);
147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ret = usageBits;
147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ret;
147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method are the overridden implementation of
148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getExtendedKeyUsage method in X509Certificate in the Sun
148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provider. It is better performance-wise since it returns cached
148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values.
148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized List<String> getExtendedKeyUsage()
148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly && extKeyUsage != null) {
148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return extKeyUsage;
149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ExtendedKeyUsageExtension ext = getExtendedKeyUsageExtension();
149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ext == null) {
149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            extKeyUsage =
149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Collections.unmodifiableList(ext.getExtendedKeyUsage());
149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return extKeyUsage;
149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This static method is the default implementation of the
150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getExtendedKeyUsage method in X509Certificate. A
150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Certificate provider generally should overwrite this to
150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provide among other things caching for better performance.
150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static List<String> getExtendedKeyUsage(X509Certificate cert)
150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] ext = cert.getExtensionValue(EXTENDED_KEY_USAGE_OID);
151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ext == null)
151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerValue val = new DerValue(ext);
151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] data = val.getOctetString();
151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ExtendedKeyUsageExtension ekuExt =
151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                new ExtendedKeyUsageExtension(Boolean.FALSE, data);
151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.unmodifiableList(ekuExt.getExtendedKeyUsage());
151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException(ioe);
152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Get the certificate constraints path length from the
152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the critical BasicConstraints extension, (oid = 2.5.29.19).
152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the length of the constraint.
152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getBasicConstraints() {
153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String extAlias = OIDMap.getName(PKIXExtensions.BasicConstraints_Id);
153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (extAlias == null)
153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            BasicConstraintsExtension certExt =
153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (BasicConstraintsExtension)this.get(extAlias);
153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (certExt == null)
153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (((Boolean)certExt.get(BasicConstraintsExtension.IS_CA)
154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 ).booleanValue() == true)
154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return ((Integer)certExt.get(
154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        BasicConstraintsExtension.PATH_LEN)).intValue();
154351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
154451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
154551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
154651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
154751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
154851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
154951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
155051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
155151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Converts a GeneralNames structure into an immutable Collection of
155251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * alternative names (subject or issuer) in the form required by
155351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link #getSubjectAlternativeNames} or
155451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link #getIssuerAlternativeNames}.
155551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
155651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param names the GeneralNames to be converted
155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return an immutable Collection of alternative names
155851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static Collection<List<?>> makeAltNames(GeneralNames names) {
156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (names.isEmpty()) {
156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.<List<?>>emptySet();
156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        List<List<?>> newNames = new ArrayList<>();
156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (GeneralName gname : names.names()) {
156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            GeneralNameInterface name = gname.getName();
156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<Object> nameEntry = new ArrayList<>(2);
156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nameEntry.add(Integer.valueOf(name.getType()));
156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (name.getType()) {
156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_RFC822:
157051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(((RFC822Name) name).getName());
157151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
157251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_DNS:
157351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(((DNSName) name).getName());
157451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
157551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_DIRECTORY:
157651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(((X500Name) name).getRFC2253Name());
157751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
157851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_URI:
157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(((URIName) name).getName());
158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_IP:
158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    nameEntry.add(((IPAddressName) name).getName());
158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (IOException ioe) {
158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // IPAddressName in cert is bogus
158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new RuntimeException("IPAddress cannot be parsed",
158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        ioe);
158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case GeneralNameInterface.NAME_OID:
159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(((OIDName) name).getOID().toString());
159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // add DER encoded form
159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                DerOutputStream derOut = new DerOutputStream();
159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    name.encode(derOut);
159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (IOException ioe) {
159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // should not occur since name has already been decoded
160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // from cert (this would indicate a bug in our code)
160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new RuntimeException("name cannot be encoded", ioe);
160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nameEntry.add(derOut.toByteArray());
160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            newNames.add(Collections.unmodifiableList(nameEntry));
160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return Collections.unmodifiableCollection(newNames);
160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Checks a Collection of altNames and clones any name entries of type
161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * byte [].
161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */ // only partially generified due to javac bug
161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static Collection<List<?>> cloneAltNames(Collection<List<?>> altNames) {
161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean mustClone = false;
161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (List<?> nameEntry : altNames) {
161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (nameEntry.get(1) instanceof byte[]) {
161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // must clone names
162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                mustClone = true;
162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mustClone) {
162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            List<List<?>> namesCopy = new ArrayList<>();
162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (List<?> nameEntry : altNames) {
162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                Object nameObject = nameEntry.get(1);
162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (nameObject instanceof byte[]) {
162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    List<Object> nameEntryCopy =
162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        new ArrayList<>(nameEntry);
163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    nameEntryCopy.set(1, ((byte[])nameObject).clone());
163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    namesCopy.add(Collections.unmodifiableList(nameEntryCopy));
163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    namesCopy.add(nameEntry);
163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.unmodifiableCollection(namesCopy);
163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return altNames;
163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method are the overridden implementation of
164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getSubjectAlternativeNames method in X509Certificate in the Sun
164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provider. It is better performance-wise since it returns cached
164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values.
164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized Collection<List<?>> getSubjectAlternativeNames()
164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // return cached value if we can
165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly && subjectAlternativeNames != null)  {
165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cloneAltNames(subjectAlternativeNames);
165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SubjectAlternativeNameExtension subjectAltNameExt =
165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getSubjectAlternativeNameExtension();
165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (subjectAltNameExt == null) {
165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        GeneralNames names;
166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
1661d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            names = subjectAltNameExt.get(
166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    SubjectAlternativeNameExtension.SUBJECT_NAME);
166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // should not occur
166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.<List<?>>emptySet();
166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        subjectAlternativeNames = makeAltNames(names);
166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return subjectAlternativeNames;
166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This static method is the default implementation of the
167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getSubjectAlternaitveNames method in X509Certificate. A
167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Certificate provider generally should overwrite this to
167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provide among other things caching for better performance.
167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static Collection<List<?>> getSubjectAlternativeNames(X509Certificate cert)
167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] ext = cert.getExtensionValue(SUBJECT_ALT_NAME_OID);
168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ext == null) {
168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerValue val = new DerValue(ext);
168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] data = val.getOctetString();
168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            SubjectAlternativeNameExtension subjectAltNameExt =
168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                new SubjectAlternativeNameExtension(Boolean.FALSE,
168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                    data);
169051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
169151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            GeneralNames names;
169251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
1693d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                names = subjectAltNameExt.get(
169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        SubjectAlternativeNameExtension.SUBJECT_NAME);
169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }  catch (IOException ioe) {
169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // should not occur
169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return Collections.<List<?>>emptySet();
169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return makeAltNames(names);
170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException(ioe);
170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method are the overridden implementation of
170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getIssuerAlternativeNames method in X509Certificate in the Sun
170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provider. It is better performance-wise since it returns cached
170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values.
171051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
171151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized Collection<List<?>> getIssuerAlternativeNames()
171251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
171351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // return cached value if we can
171451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly && issuerAlternativeNames != null) {
171551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cloneAltNames(issuerAlternativeNames);
171651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
171751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        IssuerAlternativeNameExtension issuerAltNameExt =
171851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getIssuerAlternativeNameExtension();
171951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (issuerAltNameExt == null) {
172051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        GeneralNames names;
172351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
1724d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            names = issuerAltNameExt.get(
172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    IssuerAlternativeNameExtension.ISSUER_NAME);
172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // should not occur
172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return Collections.<List<?>>emptySet();
172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        issuerAlternativeNames = makeAltNames(names);
173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return issuerAlternativeNames;
173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This static method is the default implementation of the
173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * getIssuerAlternaitveNames method in X509Certificate. A
173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * X509Certificate provider generally should overwrite this to
173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provide among other things caching for better performance.
173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static Collection<List<?>> getIssuerAlternativeNames(X509Certificate cert)
174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws CertificateParsingException {
174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] ext = cert.getExtensionValue(ISSUER_ALT_NAME_OID);
174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ext == null) {
174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return null;
174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
174851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            DerValue val = new DerValue(ext);
174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            byte[] data = val.getOctetString();
175051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
175151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            IssuerAlternativeNameExtension issuerAltNameExt =
175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                new IssuerAlternativeNameExtension(Boolean.FALSE,
175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                    data);
175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            GeneralNames names;
175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
1756d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                names = issuerAltNameExt.get(
175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        IssuerAlternativeNameExtension.ISSUER_NAME);
175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }  catch (IOException ioe) {
175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // should not occur
176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return Collections.<List<?>>emptySet();
176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return makeAltNames(names);
176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException ioe) {
176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException(ioe);
176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public AuthorityInfoAccessExtension getAuthorityInfoAccessExtension() {
176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (AuthorityInfoAccessExtension)
177051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getExtension(PKIXExtensions.AuthInfoAccess_Id);
177151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
177251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /************************************************************/
177451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
177651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Cert is a SIGNED ASN.1 macro, a three elment sequence:
177751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
177851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  - Data to be signed (ToBeSigned) -- the "raw" cert
177951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  - Signature algorithm (SigAlgId)
178051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  - The signature bits
178151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
178251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This routine unmarshals the certificate, saving the signature
178351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parts away for later verification.
178451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
178551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void parse(DerValue val)
178651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    throws CertificateException, IOException {
1787b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        parse(
1788b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            val,
1789b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            null // use re-encoded form of val as the encoded form
1790b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin            );
1791b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    }
1792b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin
1793b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    /*
1794b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * Cert is a SIGNED ASN.1 macro, a three elment sequence:
1795b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *
1796b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *  - Data to be signed (ToBeSigned) -- the "raw" cert
1797b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *  - Signature algorithm (SigAlgId)
1798b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *  - The signature bits
1799b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     *
1800b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * This routine unmarshals the certificate, saving the signature
1801b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     * parts away for later verification.
1802b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin     */
1803b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    private void parse(DerValue val, byte[] originalEncodedForm)
1804b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin    throws CertificateException, IOException {
180551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // check if can over write the certificate
180651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (readOnly)
180751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException(
180851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      "cannot over-write existing certificate");
180951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
181051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (val.data == null || val.tag != DerValue.tag_Sequence)
181151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException(
181251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      "invalid DER-encoded certificate data");
181351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1814b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin        signedCert =
1815b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin                (originalEncodedForm != null)
1816b0d4380094f020749b77df93bf9d11b6fda8d483Alex Klyubin                        ? originalEncodedForm : val.toByteArray();
181751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerValue[] seq = new DerValue[3];
181851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
181951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        seq[0] = val.data.getDerValue();
182051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        seq[1] = val.data.getDerValue();
182151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        seq[2] = val.data.getDerValue();
182251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
182351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (val.data.available() != 0) {
182451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("signed overrun, bytes = "
182551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     + val.data.available());
182651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
182751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (seq[0].tag != DerValue.tag_Sequence) {
182851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("signed fields invalid");
182951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
183051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
183151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        algId = AlgorithmId.parse(seq[1]);
183251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        signature = seq[2].getBitString();
183351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
183451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (seq[1].data.available() != 0) {
183551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("algid field overrun");
183651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
183751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (seq[2].data.available() != 0)
183851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateParsingException("signed fields overrun");
183951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
184051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // The CertificateInfo
184151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        info = new X509CertInfo(seq[0]);
184251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
184351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // the "inner" and "outer" signature algorithms must match
184451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        AlgorithmId infoSigAlg = (AlgorithmId)info.get(
184551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                              CertificateAlgorithmId.NAME
184651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                              + DOT +
184751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                              CertificateAlgorithmId.ALGORITHM);
184851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (! algId.equals(infoSigAlg))
184951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new CertificateException("Signature algorithm mismatch");
185051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        readOnly = true;
185151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
185251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
185351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
185451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Extract the subject or issuer X500Principal from an X509Certificate.
185551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Parses the encoded form of the cert to preserve the principal's
185651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ASN.1 encoding.
185751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
185851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static X500Principal getX500Principal(X509Certificate cert,
185951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean getIssuer) throws Exception {
186051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] encoded = cert.getEncoded();
186151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerInputStream derIn = new DerInputStream(encoded);
186251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerValue tbsCert = derIn.getSequence(3)[0];
186351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerInputStream tbsIn = tbsCert.data;
186451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DerValue tmp;
186551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        tmp = tbsIn.getDerValue();
186651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // skip version number if present
186751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tmp.isContextSpecific((byte)0)) {
186851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          tmp = tbsIn.getDerValue();
186951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
187051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // tmp always contains serial number now
187151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        tmp = tbsIn.getDerValue();              // skip signature
187251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        tmp = tbsIn.getDerValue();              // issuer
187351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (getIssuer == false) {
187451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            tmp = tbsIn.getDerValue();          // skip validity
187551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            tmp = tbsIn.getDerValue();          // subject
187651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
187751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        byte[] principalBytes = tmp.toByteArray();
187851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new X500Principal(principalBytes);
187951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
188051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
188151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
188251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Extract the subject X500Principal from an X509Certificate.
188351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Called from java.security.cert.X509Certificate.getSubjectX500Principal().
188451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
188551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static X500Principal getSubjectX500Principal(X509Certificate cert) {
188651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
188751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return getX500Principal(cert, false);
188851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
188951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException("Could not parse subject", e);
189051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Extract the issuer X500Principal from an X509Certificate.
189551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Called from java.security.cert.X509Certificate.getIssuerX500Principal().
189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static X500Principal getIssuerX500Principal(X509Certificate cert) {
189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return getX500Principal(cert, true);
190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new RuntimeException("Could not parse issuer", e);
190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returned the encoding of the given certificate for internal use.
190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Callers must guarantee that they neither modify it nor expose it
190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to untrusted code. Uses getEncodedInternal() if the certificate
190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is instance of X509CertImpl, getEncoded() otherwise.
191051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static byte[] getEncodedInternal(Certificate cert)
191251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws CertificateEncodingException {
191351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cert instanceof X509CertImpl) {
191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return ((X509CertImpl)cert).getEncodedInternal();
191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cert.getEncoded();
191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
192151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Utility method to convert an arbitrary instance of X509Certificate
192251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to a X509CertImpl. Does a cast if possible, otherwise reparses
192351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the encoding.
192451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
192551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static X509CertImpl toImpl(X509Certificate cert)
192651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throws CertificateException {
192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cert instanceof X509CertImpl) {
192851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (X509CertImpl)cert;
192951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return X509Factory.intern(cert);
193151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
193251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
193351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
193451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
193551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Utility method to test if a certificate is self-issued. This is
193651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the case iff the subject and issuer X500Principals are equal.
193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
193851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static boolean isSelfIssued(X509Certificate cert) {
193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        X500Principal subject = cert.getSubjectX500Principal();
194051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        X500Principal issuer = cert.getIssuerX500Principal();
194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return subject.equals(issuer);
194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Utility method to test if a certificate is self-signed. This is
194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the case iff the subject and issuer X500Principals are equal
194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * AND the certificate's subject public key can be used to verify
194851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the certificate. In case of exception, returns false.
194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static boolean isSelfSigned(X509Certificate cert,
195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String sigProvider) {
195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (isSelfIssued(cert)) {
195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
195451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (sigProvider == null) {
195551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    cert.verify(cert.getPublicKey());
195651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
195751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    cert.verify(cert.getPublicKey(), sigProvider);
195851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
195951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return true;
196051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (Exception e) {
196151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // In case of exception, return false
196251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
196351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
196451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
196551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
1966d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
1967d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    private ConcurrentHashMap<String,String> fingerprints =
1968d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            new ConcurrentHashMap<>(2);
1969d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
19706975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer// BEGIN Android-removed
19716975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer//    public String getFingerprint(String algorithm) {
19726975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer//        return fingerprints.computeIfAbsent(algorithm,
19738b5ba217ca0e811a8e8602666b10f3b3e0bcc62cPrzemyslaw Szczepaniak//                x -> getFingerprint(x, this));
19746975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer//    }
19756975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer// END Android-removed
1976d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
1977d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    /**
1978d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     * Gets the requested finger print of the certificate. The result
1979d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     * only contains 0-9 and A-F. No small case, no colon.
1980d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     */
19818b5ba217ca0e811a8e8602666b10f3b3e0bcc62cPrzemyslaw Szczepaniak    public static String getFingerprint(String algorithm,
19828b5ba217ca0e811a8e8602666b10f3b3e0bcc62cPrzemyslaw Szczepaniak            X509Certificate cert) {
1983d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        String fingerPrint = "";
1984d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        try {
19858b5ba217ca0e811a8e8602666b10f3b3e0bcc62cPrzemyslaw Szczepaniak            byte[] encCertInfo = cert.getEncoded();
19868b5ba217ca0e811a8e8602666b10f3b3e0bcc62cPrzemyslaw Szczepaniak            MessageDigest md = MessageDigest.getInstance(algorithm);
1987d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            byte[] digest = md.digest(encCertInfo);
1988d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            StringBuffer buf = new StringBuffer();
1989d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            for (int i = 0; i < digest.length; i++) {
1990d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                byte2hex(digest[i], buf);
1991d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            }
1992d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            fingerPrint = buf.toString();
1993d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
1994d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root            // ignored
1995d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        }
1996d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        return fingerPrint;
1997d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    }
1998d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root
1999d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    /**
2000d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     * Converts a byte to hex digit and writes to the supplied buffer
2001d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root     */
2002d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    private static void byte2hex(byte b, StringBuffer buf) {
2003d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
2004d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root                '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2005d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        int high = ((b & 0xf0) >> 4);
2006d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        int low = (b & 0x0f);
2007d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        buf.append(hexChars[high]);
2008d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root        buf.append(hexChars[low]);
2009d7819a81f8b1b8d1a6b26329e4aa5f046afbf1f6Kenny Root    }
201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
2011