Java example source code file (X509CertSelector.java)
This example Java source code file (X509CertSelector.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
The X509CertSelector.java Java example source code
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.security.cert;
import java.io.IOException;
import java.math.BigInteger;
import java.security.PublicKey;
import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.misc.HexDumpEncoder;
import sun.security.util.Debug;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.*;
/**
* A {@code CertSelector} that selects {@code X509Certificates} that
* match all specified criteria. This class is particularly useful when
* selecting certificates from a {@code CertStore} to build a
* PKIX-compliant certification path.
* <p>
* When first constructed, an {@code X509CertSelector} has no criteria
* enabled and each of the {@code get} methods return a default value
* ({@code null}, or {@code -1} for the {@link #getBasicConstraints
* getBasicConstraints} method). Therefore, the {@link #match match}
* method would return {@code true} for any {@code X509Certificate}.
* Typically, several criteria are enabled (by calling
* {@link #setIssuer setIssuer} or
* {@link #setKeyUsage setKeyUsage}, for instance) and then the
* {@code X509CertSelector} is passed to
* {@link CertStore#getCertificates CertStore.getCertificates} or some similar
* method.
* <p>
* Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
* and {@link #setSerialNumber setSerialNumber},
* for example) such that the {@code match} method
* usually uniquely matches a single {@code X509Certificate}. We say
* usually, since it is possible for two issuing CAs to have the same
* distinguished name and each issue a certificate with the same serial
* number. Other unique combinations include the issuer, subject,
* subjectKeyIdentifier and/or the subjectPublicKey criteria.
* <p>
* Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
* Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
* definitions of the X.509 certificate extensions mentioned below.
* <p>
* <b>Concurrent Access
* <p>
* Unless otherwise specified, the methods defined in this class are not
* thread-safe. Multiple threads that need to access a single
* object concurrently should synchronize amongst themselves and
* provide the necessary locking. Multiple threads each manipulating
* separate objects need not synchronize.
*
* @see CertSelector
* @see X509Certificate
*
* @since 1.4
* @author Steve Hanna
*/
public class X509CertSelector implements CertSelector {
private static final Debug debug = Debug.getInstance("certpath");
private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
static {
CertPathHelperImpl.initialize();
}
private BigInteger serialNumber;
private X500Principal issuer;
private X500Principal subject;
private byte[] subjectKeyID;
private byte[] authorityKeyID;
private Date certificateValid;
private Date privateKeyValid;
private ObjectIdentifier subjectPublicKeyAlgID;
private PublicKey subjectPublicKey;
private byte[] subjectPublicKeyBytes;
private boolean[] keyUsage;
private Set<String> keyPurposeSet;
private Set<ObjectIdentifier> keyPurposeOIDSet;
private Set<List subjectAlternativeNames;
private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
private CertificatePolicySet policy;
private Set<String> policySet;
private Set<List pathToNames;
private Set<GeneralNameInterface> pathToGeneralNames;
private NameConstraintsExtension nc;
private byte[] ncBytes;
private int basicConstraints = -1;
private X509Certificate x509Cert;
private boolean matchAllSubjectAltNames = true;
private static final Boolean FALSE = Boolean.FALSE;
private static final int PRIVATE_KEY_USAGE_ID = 0;
private static final int SUBJECT_ALT_NAME_ID = 1;
private static final int NAME_CONSTRAINTS_ID = 2;
private static final int CERT_POLICIES_ID = 3;
private static final int EXTENDED_KEY_USAGE_ID = 4;
private static final int NUM_OF_EXTENSIONS = 5;
private static final String[] EXTENSION_OIDS = new String[NUM_OF_EXTENSIONS];
static {
EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16";
EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17";
EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30";
EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32";
EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
};
/* Constants representing the GeneralName types */
static final int NAME_ANY = 0;
static final int NAME_RFC822 = 1;
static final int NAME_DNS = 2;
static final int NAME_X400 = 3;
static final int NAME_DIRECTORY = 4;
static final int NAME_EDI = 5;
static final int NAME_URI = 6;
static final int NAME_IP = 7;
static final int NAME_OID = 8;
/**
* Creates an {@code X509CertSelector}. Initially, no criteria are set
* so any {@code X509Certificate} will match.
*/
public X509CertSelector() {
// empty
}
/**
* Sets the certificateEquals criterion. The specified
* {@code X509Certificate} must be equal to the
* {@code X509Certificate} passed to the {@code match} method.
* If {@code null}, then this check is not applied.
*
* <p>This method is particularly useful when it is necessary to
* match a single certificate. Although other criteria can be specified
* in conjunction with the certificateEquals criterion, it is usually not
* practical or necessary.
*
* @param cert the {@code X509Certificate} to match (or
* {@code null})
* @see #getCertificate
*/
public void setCertificate(X509Certificate cert) {
x509Cert = cert;
}
/**
* Sets the serialNumber criterion. The specified serial number
* must match the certificate serial number in the
* {@code X509Certificate}. If {@code null}, any certificate
* serial number will do.
*
* @param serial the certificate serial number to match
* (or {@code null})
* @see #getSerialNumber
*/
public void setSerialNumber(BigInteger serial) {
serialNumber = serial;
}
/**
* Sets the issuer criterion. The specified distinguished name
* must match the issuer distinguished name in the
* {@code X509Certificate}. If {@code null}, any issuer
* distinguished name will do.
*
* @param issuer a distinguished name as X500Principal
* (or {@code null})
* @since 1.5
*/
public void setIssuer(X500Principal issuer) {
this.issuer = issuer;
}
/**
* <strong>Denigrated, use {@linkplain #setIssuer(X500Principal)}
* or {@linkplain #setIssuer(byte[])} instead. This method should not be
* relied on as it can fail to match some certificates because of a loss of
* encoding information in the
* <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253 String form
* of some distinguished names.
* <p>
* Sets the issuer criterion. The specified distinguished name
* must match the issuer distinguished name in the
* {@code X509Certificate}. If {@code null}, any issuer
* distinguished name will do.
* <p>
* If {@code issuerDN} is not {@code null}, it should contain a
* distinguished name, in RFC 2253 format.
*
* @param issuerDN a distinguished name in RFC 2253 format
* (or {@code null})
* @throws IOException if a parsing error occurs (incorrect form for DN)
*/
public void setIssuer(String issuerDN) throws IOException {
if (issuerDN == null) {
issuer = null;
} else {
issuer = new X500Name(issuerDN).asX500Principal();
}
}
/**
* Sets the issuer criterion. The specified distinguished name
* must match the issuer distinguished name in the
* {@code X509Certificate}. If {@code null} is specified,
* the issuer criterion is disabled and any issuer distinguished name will
* do.
* <p>
* If {@code issuerDN} is not {@code null}, it should contain a
* single DER encoded distinguished name, as defined in X.501. The ASN.1
* notation for this structure is as follows.
* <pre>{@code
* Name ::= CHOICE {
* RDNSequence }
*
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
*
* RelativeDistinguishedName ::=
* SET SIZE (1 .. MAX) OF AttributeTypeAndValue
*
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY DEFINED BY AttributeType
* ....
* DirectoryString ::= CHOICE {
* teletexString TeletexString (SIZE (1..MAX)),
* printableString PrintableString (SIZE (1..MAX)),
* universalString UniversalString (SIZE (1..MAX)),
* utf8String UTF8String (SIZE (1.. MAX)),
* bmpString BMPString (SIZE (1..MAX)) }
* }</pre>
* <p>
* Note that the byte array specified here is cloned to protect against
* subsequent modifications.
*
* @param issuerDN a byte array containing the distinguished name
* in ASN.1 DER encoded form (or {@code null})
* @throws IOException if an encoding error occurs (incorrect form for DN)
*/
public void setIssuer(byte[] issuerDN) throws IOException {
try {
issuer = (issuerDN == null ? null : new X500Principal(issuerDN));
} catch (IllegalArgumentException e) {
throw new IOException("Invalid name", e);
}
}
/**
* Sets the subject criterion. The specified distinguished name
* must match the subject distinguished name in the
* {@code X509Certificate}. If {@code null}, any subject
* distinguished name will do.
*
* @param subject a distinguished name as X500Principal
* (or {@code null})
* @since 1.5
*/
public void setSubject(X500Principal subject) {
this.subject = subject;
}
/**
* <strong>Denigrated, use {@linkplain #setSubject(X500Principal)}
* or {@linkplain #setSubject(byte[])} instead. This method should not be
* relied on as it can fail to match some certificates because of a loss of
* encoding information in the RFC 2253 String form of some distinguished
* names.
* <p>
* Sets the subject criterion. The specified distinguished name
* must match the subject distinguished name in the
* {@code X509Certificate}. If {@code null}, any subject
* distinguished name will do.
* <p>
* If {@code subjectDN} is not {@code null}, it should contain a
* distinguished name, in RFC 2253 format.
*
* @param subjectDN a distinguished name in RFC 2253 format
* (or {@code null})
* @throws IOException if a parsing error occurs (incorrect form for DN)
*/
public void setSubject(String subjectDN) throws IOException {
if (subjectDN == null) {
subject = null;
} else {
subject = new X500Name(subjectDN).asX500Principal();
}
}
/**
* Sets the subject criterion. The specified distinguished name
* must match the subject distinguished name in the
* {@code X509Certificate}. If {@code null}, any subject
* distinguished name will do.
* <p>
* If {@code subjectDN} is not {@code null}, it should contain a
* single DER encoded distinguished name, as defined in X.501. For the ASN.1
* notation for this structure, see
* {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
*
* @param subjectDN a byte array containing the distinguished name in
* ASN.1 DER format (or {@code null})
* @throws IOException if an encoding error occurs (incorrect form for DN)
*/
public void setSubject(byte[] subjectDN) throws IOException {
try {
subject = (subjectDN == null ? null : new X500Principal(subjectDN));
} catch (IllegalArgumentException e) {
throw new IOException("Invalid name", e);
}
}
/**
* Sets the subjectKeyIdentifier criterion. The
* {@code X509Certificate} must contain a SubjectKeyIdentifier
* extension for which the contents of the extension
* matches the specified criterion value.
* If the criterion value is {@code null}, no
* subjectKeyIdentifier check will be done.
* <p>
* If {@code subjectKeyID} is not {@code null}, it
* should contain a single DER encoded value corresponding to the contents
* of the extension value (not including the object identifier,
* criticality setting, and encapsulating OCTET STRING)
* for a SubjectKeyIdentifier extension.
* The ASN.1 notation for this structure follows.
*
* <pre>{@code
* SubjectKeyIdentifier ::= KeyIdentifier
*
* KeyIdentifier ::= OCTET STRING
* }</pre>
* <p>
* Since the format of subject key identifiers is not mandated by
* any standard, subject key identifiers are not parsed by the
* {@code X509CertSelector}. Instead, the values are compared using
* a byte-by-byte comparison.
* <p>
* Note that the byte array supplied here is cloned to protect against
* subsequent modifications.
*
* @param subjectKeyID the subject key identifier (or {@code null})
* @see #getSubjectKeyIdentifier
*/
public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
if (subjectKeyID == null) {
this.subjectKeyID = null;
} else {
this.subjectKeyID = subjectKeyID.clone();
}
}
/**
* Sets the authorityKeyIdentifier criterion. The
* {@code X509Certificate} must contain an
* AuthorityKeyIdentifier extension for which the contents of the
* extension value matches the specified criterion value.
* If the criterion value is {@code null}, no
* authorityKeyIdentifier check will be done.
* <p>
* If {@code authorityKeyID} is not {@code null}, it
* should contain a single DER encoded value corresponding to the contents
* of the extension value (not including the object identifier,
* criticality setting, and encapsulating OCTET STRING)
* for an AuthorityKeyIdentifier extension.
* The ASN.1 notation for this structure follows.
*
* <pre>{@code
* AuthorityKeyIdentifier ::= SEQUENCE {
* keyIdentifier [0] KeyIdentifier OPTIONAL,
* authorityCertIssuer [1] GeneralNames OPTIONAL,
* authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
*
* KeyIdentifier ::= OCTET STRING
* }</pre>
* <p>
* Authority key identifiers are not parsed by the
* {@code X509CertSelector}. Instead, the values are
* compared using a byte-by-byte comparison.
* <p>
* When the {@code keyIdentifier} field of
* {@code AuthorityKeyIdentifier} is populated, the value is
* usually taken from the {@code SubjectKeyIdentifier} extension
* in the issuer's certificate. Note, however, that the result of
* {@code X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object
* Identifier>)} on the issuer's certificate may NOT be used
* directly as the input to {@code setAuthorityKeyIdentifier}.
* This is because the SubjectKeyIdentifier contains
* only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
* KeyIdentifier, GeneralNames, and CertificateSerialNumber.
* In order to use the extension value of the issuer certificate's
* {@code SubjectKeyIdentifier}
* extension, it will be necessary to extract the value of the embedded
* {@code KeyIdentifier} OCTET STRING, then DER encode this OCTET
* STRING inside a SEQUENCE.
* For more details on SubjectKeyIdentifier, see
* {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
* <p>
* Note also that the byte array supplied here is cloned to protect against
* subsequent modifications.
*
* @param authorityKeyID the authority key identifier
* (or {@code null})
* @see #getAuthorityKeyIdentifier
*/
public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
if (authorityKeyID == null) {
this.authorityKeyID = null;
} else {
this.authorityKeyID = authorityKeyID.clone();
}
}
/**
* Sets the certificateValid criterion. The specified date must fall
* within the certificate validity period for the
* {@code X509Certificate}. If {@code null}, no certificateValid
* check will be done.
* <p>
* Note that the {@code Date} supplied here is cloned to protect
* against subsequent modifications.
*
* @param certValid the {@code Date} to check (or {@code null})
* @see #getCertificateValid
*/
public void setCertificateValid(Date certValid) {
if (certValid == null) {
certificateValid = null;
} else {
certificateValid = (Date)certValid.clone();
}
}
/**
* Sets the privateKeyValid criterion. The specified date must fall
* within the private key validity period for the
* {@code X509Certificate}. If {@code null}, no privateKeyValid
* check will be done.
* <p>
* Note that the {@code Date} supplied here is cloned to protect
* against subsequent modifications.
*
* @param privateKeyValid the {@code Date} to check (or
* {@code null})
* @see #getPrivateKeyValid
*/
public void setPrivateKeyValid(Date privateKeyValid) {
if (privateKeyValid == null) {
this.privateKeyValid = null;
} else {
this.privateKeyValid = (Date)privateKeyValid.clone();
}
}
/**
* Sets the subjectPublicKeyAlgID criterion. The
* {@code X509Certificate} must contain a subject public key
* with the specified algorithm. If {@code null}, no
* subjectPublicKeyAlgID check will be done.
*
* @param oid The object identifier (OID) of the algorithm to check
* for (or {@code null}). An OID is represented by a
* set of nonnegative integers separated by periods.
* @throws IOException if the OID is invalid, such as
* the first component being not 0, 1 or 2 or the second component
* being greater than 39.
*
* @see #getSubjectPublicKeyAlgID
*/
public void setSubjectPublicKeyAlgID(String oid) throws IOException {
if (oid == null) {
subjectPublicKeyAlgID = null;
} else {
subjectPublicKeyAlgID = new ObjectIdentifier(oid);
}
}
/**
* Sets the subjectPublicKey criterion. The
* {@code X509Certificate} must contain the specified subject public
* key. If {@code null}, no subjectPublicKey check will be done.
*
* @param key the subject public key to check for (or {@code null})
* @see #getSubjectPublicKey
*/
public void setSubjectPublicKey(PublicKey key) {
if (key == null) {
subjectPublicKey = null;
subjectPublicKeyBytes = null;
} else {
subjectPublicKey = key;
subjectPublicKeyBytes = key.getEncoded();
}
}
/**
* Sets the subjectPublicKey criterion. The {@code X509Certificate}
* must contain the specified subject public key. If {@code null},
* no subjectPublicKey check will be done.
* <p>
* Because this method allows the public key to be specified as a byte
* array, it may be used for unknown key types.
* <p>
* If {@code key} is not {@code null}, it should contain a
* single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
* The ASN.1 notation for this structure is as follows.
* <pre>{@code
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* -- contains a value of the type
* -- registered for use with the
* -- algorithm object identifier value
* }</pre>
* <p>
* Note that the byte array supplied here is cloned to protect against
* subsequent modifications.
*
* @param key a byte array containing the subject public key in ASN.1 DER
* form (or {@code null})
* @throws IOException if an encoding error occurs (incorrect form for
* subject public key)
* @see #getSubjectPublicKey
*/
public void setSubjectPublicKey(byte[] key) throws IOException {
if (key == null) {
subjectPublicKey = null;
subjectPublicKeyBytes = null;
} else {
subjectPublicKeyBytes = key.clone();
subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
}
}
/**
* Sets the keyUsage criterion. The {@code X509Certificate}
* must allow the specified keyUsage values. If {@code null}, no
* keyUsage check will be done. Note that an {@code X509Certificate}
* that has no keyUsage extension implicitly allows all keyUsage values.
* <p>
* Note that the boolean array supplied here is cloned to protect against
* subsequent modifications.
*
* @param keyUsage a boolean array in the same format as the boolean
* array returned by
* {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
* Or {@code null}.
* @see #getKeyUsage
*/
public void setKeyUsage(boolean[] keyUsage) {
if (keyUsage == null) {
this.keyUsage = null;
} else {
this.keyUsage = keyUsage.clone();
}
}
/**
* Sets the extendedKeyUsage criterion. The {@code X509Certificate}
* must allow the specified key purposes in its extended key usage
* extension. If {@code keyPurposeSet} is empty or {@code null},
* no extendedKeyUsage check will be done. Note that an
* {@code X509Certificate} that has no extendedKeyUsage extension
* implicitly allows all key purposes.
* <p>
* Note that the {@code Set} is cloned to protect against
* subsequent modifications.
*
* @param keyPurposeSet a {@code Set} of key purpose OIDs in string
* format (or {@code null}). Each OID is represented by a set of
* nonnegative integers separated by periods.
* @throws IOException if the OID is invalid, such as
* the first component being not 0, 1 or 2 or the second component
* being greater than 39.
* @see #getExtendedKeyUsage
*/
public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException {
if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
this.keyPurposeSet = null;
keyPurposeOIDSet = null;
} else {
this.keyPurposeSet =
Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet));
keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
for (String s : this.keyPurposeSet) {
keyPurposeOIDSet.add(new ObjectIdentifier(s));
}
}
}
/**
* Enables/disables matching all of the subjectAlternativeNames
* specified in the {@link #setSubjectAlternativeNames
* setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
* addSubjectAlternativeName} methods. If enabled,
* the {@code X509Certificate} must contain all of the
* specified subject alternative names. If disabled, the
* {@code X509Certificate} must contain at least one of the
* specified subject alternative names.
*
* <p>The matchAllNames flag is {@code true} by default.
*
* @param matchAllNames if {@code true}, the flag is enabled;
* if {@code false}, the flag is disabled.
* @see #getMatchAllSubjectAltNames
*/
public void setMatchAllSubjectAltNames(boolean matchAllNames) {
this.matchAllSubjectAltNames = matchAllNames;
}
/**
* Sets the subjectAlternativeNames criterion. The
* {@code X509Certificate} must contain all or at least one of the
* specified subjectAlternativeNames, depending on the value of
* the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
* setMatchAllSubjectAltNames}).
* <p>
* This method allows the caller to specify, with a single method call,
* the complete set of subject alternative names for the
* subjectAlternativeNames criterion. The specified value replaces
* the previous value for the subjectAlternativeNames criterion.
* <p>
* The {@code names} parameter (if not {@code null}) is a
* {@code Collection} with one
* entry for each name to be included in the subject alternative name
* criterion. Each entry is a {@code List} whose first entry is an
* {@code Integer} (the name type, 0-8) and whose second
* entry is a {@code String} or a byte array (the name, in
* string or ASN.1 DER encoded form, respectively).
* There can be multiple names of the same type. If {@code null}
* is supplied as the value for this argument, no
* subjectAlternativeNames check will be performed.
* <p>
* Each subject alternative name in the {@code Collection}
* may be specified either as a {@code String} or as an ASN.1 encoded
* byte array. For more details about the formats used, see
* {@link #addSubjectAlternativeName(int type, String name)
* addSubjectAlternativeName(int type, String name)} and
* {@link #addSubjectAlternativeName(int type, byte [] name)
* addSubjectAlternativeName(int type, byte [] name)}.
* <p>
* <strong>Note: for distinguished names, specify the byte
* array form instead of the String form. See the note in
* {@link #addSubjectAlternativeName(int, String)} for more information.
* <p>
* Note that the {@code names} parameter can contain duplicate
* names (same name and name type), but they may be removed from the
* {@code Collection} of names returned by the
* {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
* <p>
* Note that a deep copy is performed on the {@code Collection} to
* protect against subsequent modifications.
*
* @param names a {@code Collection} of names (or {@code null})
* @throws IOException if a parsing error occurs
* @see #getSubjectAlternativeNames
*/
public void setSubjectAlternativeNames(Collection<List names)
throws IOException {
if (names == null) {
subjectAlternativeNames = null;
subjectAlternativeGeneralNames = null;
} else {
if (names.isEmpty()) {
subjectAlternativeNames = null;
subjectAlternativeGeneralNames = null;
return;
}
Set<List tempNames = cloneAndCheckNames(names);
// Ensure that we either set both of these or neither
subjectAlternativeGeneralNames = parseNames(tempNames);
subjectAlternativeNames = tempNames;
}
}
/**
* Adds a name to the subjectAlternativeNames criterion. The
* {@code X509Certificate} must contain all or at least one
* of the specified subjectAlternativeNames, depending on the value of
* the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
* setMatchAllSubjectAltNames}).
* <p>
* This method allows the caller to add a name to the set of subject
* alternative names.
* The specified name is added to any previous value for the
* subjectAlternativeNames criterion. If the specified name is a
* duplicate, it may be ignored.
* <p>
* The name is provided in string format.
* <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822, DNS, and URI
* names use the well-established string formats for those types (subject to
* the restrictions included in RFC 3280). IPv4 address names are
* supplied using dotted quad notation. OID address names are represented
* as a series of nonnegative integers separated by periods. And
* directory names (distinguished names) are supplied in RFC 2253 format.
* No standard string format is defined for otherNames, X.400 names,
* EDI party names, IPv6 address names, or any other type of names. They
* should be specified using the
* {@link #addSubjectAlternativeName(int type, byte [] name)
* addSubjectAlternativeName(int type, byte [] name)}
* method.
* <p>
* <strong>Note: for distinguished names, use
* {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
* This method should not be relied on as it can fail to match some
* certificates because of a loss of encoding information in the RFC 2253
* String form of some distinguished names.
*
* @param type the name type (0-8, as specified in
* RFC 3280, section 4.2.1.7)
* @param name the name in string form (not {@code null})
* @throws IOException if a parsing error occurs
*/
public void addSubjectAlternativeName(int type, String name)
throws IOException {
addSubjectAlternativeNameInternal(type, name);
}
/**
* Adds a name to the subjectAlternativeNames criterion. The
* {@code X509Certificate} must contain all or at least one
* of the specified subjectAlternativeNames, depending on the value of
* the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
* setMatchAllSubjectAltNames}).
* <p>
* This method allows the caller to add a name to the set of subject
* alternative names.
* The specified name is added to any previous value for the
* subjectAlternativeNames criterion. If the specified name is a
* duplicate, it may be ignored.
* <p>
* The name is provided as a byte array. This byte array should contain
* the DER encoded name, as it would appear in the GeneralName structure
* defined in RFC 3280 and X.509. The encoded byte array should only contain
* the encoded value of the name, and should not include the tag associated
* with the name in the GeneralName structure. The ASN.1 definition of this
* structure appears below.
* <pre>{@code
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] Name,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER}
* }</pre>
* <p>
* Note that the byte array supplied here is cloned to protect against
* subsequent modifications.
*
* @param type the name type (0-8, as listed above)
* @param name a byte array containing the name in ASN.1 DER encoded form
* @throws IOException if a parsing error occurs
*/
public void addSubjectAlternativeName(int type, byte[] name)
throws IOException {
// clone because byte arrays are modifiable
addSubjectAlternativeNameInternal(type, name.clone());
}
/**
* A private method that adds a name (String or byte array) to the
* subjectAlternativeNames criterion. The {@code X509Certificate}
* must contain the specified subjectAlternativeName.
*
* @param type the name type (0-8, as specified in
* RFC 3280, section 4.2.1.7)
* @param name the name in string or byte array form
* @throws IOException if a parsing error occurs
*/
private void addSubjectAlternativeNameInternal(int type, Object name)
throws IOException {
// First, ensure that the name parses
GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
if (subjectAlternativeNames == null) {
subjectAlternativeNames = new HashSet<List();
}
if (subjectAlternativeGeneralNames == null) {
subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
}
List<Object> list = new ArrayList