FileDocCategorySizeDatePackage
X509CertSelector.javaAPI DocAndroid 1.5 API53861Wed May 06 22:41:06 BST 2009java.security.cert

X509CertSelector

public class X509CertSelector extends Object implements CertSelector
A certificate selector ({@code CertSelector} for selecting {@code X509Certificate}s that match the specified criteria.
since
Android 1.0

Fields Summary
private X509Certificate
certificateEquals
private BigInteger
serialNumber
private X500Principal
issuer
private X500Principal
subject
private byte[]
subjectKeyIdentifier
private byte[]
authorityKeyIdentifier
private Date
certificateValid
private String
subjectPublicKeyAlgID
private Date
privateKeyValid
private byte[]
subjectPublicKey
private boolean[]
keyUsage
private Set
extendedKeyUsage
private boolean
matchAllNames
private int
pathLen
private List[]
subjectAltNames
private org.apache.harmony.security.x509.NameConstraints
nameConstraints
private Set
policies
private ArrayList
pathToNames
private PublicKey
subjectPublicKeyImpl
private String
issuerName
private byte[]
issuerBytes
Constructors Summary
public X509CertSelector()
Creates a new {@code X509CertSelector}.

since
Android 1.0


                  
      
Methods Summary
public voidaddPathToName(int type, java.lang.String name)
Adds a {@literal "pathToName"} to the respective criterion.

param
type the type of the name.
param
name the name in string format.
throws
IOException if parsing fails.
see
#setPathToNames
since
Android 1.0

        GeneralName path_name = new GeneralName(type, name);
        // create only if there was not any errors
        if (pathToNames == null) {
            pathToNames = new ArrayList();
        }
        pathToNames.add(path_name);
    
public voidaddPathToName(int type, byte[] name)
Adds a {@literal "pathToName"} to the respective criterion.

param
type the type of the name
param
name the name in ASN.1 DER encoded form.
throws
IOException if decoding fails.
see
#setPathToNames
since
Android 1.0

        GeneralName path_name= new GeneralName(type, name);
        // create only if there was not any errors
        if (pathToNames == null) {
            pathToNames = new ArrayList();
        }
        pathToNames.add(path_name);
    
public voidaddSubjectAlternativeName(int tag, java.lang.String name)
Adds a subject alternative name to the respective criterion.

param
tag the type of the name
param
name the name in string format.
throws
IOException if parsing the name fails.
since
Android 1.0

        GeneralName alt_name = new GeneralName(tag, name);
        // create only if there was not any errors
        if (subjectAltNames == null) {
            subjectAltNames = new ArrayList[9];
        }
        if (subjectAltNames[tag] == null) {
            subjectAltNames[tag] = new ArrayList();
        }
        subjectAltNames[tag].add(alt_name);
    
public voidaddSubjectAlternativeName(int tag, byte[] name)
Adds a subject alternative name to the respective criterion.

param
tag the type of the name.
param
name the name in ASN.1 DER encoded form.
throws
IOException if the decoding of the name fails.
since
Android 1.0

        GeneralName alt_name = new GeneralName(tag, name);
        // create only if there was not any errors
        if (subjectAltNames == null) {
            subjectAltNames = new ArrayList[9];
        }
        if (subjectAltNames[tag] == null) {
            subjectAltNames[tag] = new ArrayList();
        }
        subjectAltNames[tag].add(alt_name);
    
private voidcheckOID(java.lang.String oid)

        int beg = 0;
        int end = oid.indexOf('.", beg);
        try {
            int comp = Integer.parseInt(oid.substring(beg, end));
            beg = end + 1;
            if ((comp < 0) || (comp > 2)) {
                throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
            }
            end = oid.indexOf('.", beg);
            comp = Integer.parseInt(oid.substring(beg, end));
            if ((comp < 0) || (comp > 39)) {
                throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
            }
        } catch (IndexOutOfBoundsException e) {
            throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
        } catch (NumberFormatException e) {
            throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
        }
    
public java.lang.Objectclone()
Clones this {@code X509CertSelector} instance.

return
the cloned instance.
since
Android 1.0

        X509CertSelector result = new X509CertSelector();
        result.certificateEquals = this.certificateEquals;
        result.serialNumber = this.serialNumber;
        result.issuer = this.issuer;
        result.subject = this.subject;
        if (this.subjectKeyIdentifier != null) {
            result.subjectKeyIdentifier =
                new byte[this.subjectKeyIdentifier.length];
            System.arraycopy(this.subjectKeyIdentifier, 0,
                    result.subjectKeyIdentifier, 0,
                    this.subjectKeyIdentifier.length);
        }
        if (this.authorityKeyIdentifier != null) {
            result.authorityKeyIdentifier =
                new byte[this.authorityKeyIdentifier.length];
            System.arraycopy(this.authorityKeyIdentifier, 0,
                    result.authorityKeyIdentifier, 0,
                    this.authorityKeyIdentifier.length);
        }
        result.certificateValid = this.certificateValid;
        result.subjectPublicKeyAlgID = this.subjectPublicKeyAlgID;
        result.privateKeyValid = this.privateKeyValid;
        if (this.subjectPublicKey != null) {
            result.subjectPublicKey = new byte[this.subjectPublicKey.length];
            System.arraycopy(this.subjectPublicKey, 0, result.subjectPublicKey,
                    0, this.subjectPublicKey.length);
        }
        if (this.keyUsage != null) {
            result.keyUsage = new boolean[this.keyUsage.length];
            System.arraycopy(this.keyUsage, 0, result.keyUsage, 0,
                    this.keyUsage.length);
        }
        result.extendedKeyUsage = (this.extendedKeyUsage == null)
            ? null
            : new HashSet(this.extendedKeyUsage);
        result.matchAllNames = this.matchAllNames;
        result.pathLen = this.pathLen;
        if (this.subjectAltNames != null) {
            result.subjectAltNames = new ArrayList[9];
            for (int i=0; i<9; i++) {
                if (this.subjectAltNames[i] != null) {
                    result.subjectAltNames[i] =
                        new ArrayList(this.subjectAltNames[i]);
                }
            }
        }
        result.nameConstraints = this.nameConstraints;
        result.policies = (this.policies == null)
            ? null
            : new HashSet(this.policies);
        result.pathToNames = (this.pathToNames == null)
            ? null
            : new ArrayList(this.pathToNames);
        result.subjectPublicKeyImpl = this.subjectPublicKeyImpl;

        return result;
    
public byte[]getAuthorityKeyIdentifier()
Returns the criterion for the {@literal AuthorityKeyIdentifier} extension.

return
the authority key identifier, or {@code null} if it is not to be checked.
since
Android 1.0

        if (authorityKeyIdentifier == null) {
            return null;
        }
        byte[] res = new byte[authorityKeyIdentifier.length];
        System.arraycopy(authorityKeyIdentifier, 0, res, 0, res.length);
        return res;
    
public intgetBasicConstraints()
Returns the criterion for the basic constraints extension.

A value greater than or equal to zero indicates that a certificate must include a basic constraints extension with a path length of a least that value. A value of {@code -2} indicates that only end-entity certificates are accepted. A value of {@code -1} indicates that no check is done.

return
the value of the criterion.
since
Android 1.0

        return pathLen;
    
private java.lang.StringgetBytesAsString(byte[] data)

        String result = ""; //$NON-NLS-1$
        for (int i=0; i<data.length; i++) {
            String tail = Integer.toHexString(0x00ff & data[i]);
            if (tail.length() == 1) {
                tail = "0" + tail; //$NON-NLS-1$
            }
            result += tail + " "; //$NON-NLS-1$
        }
        return result;
    
public java.security.cert.X509CertificategetCertificate()
Returns the certificate that a matching certificate must be equal to.

return
the certificate to match, or null if this criteria is not checked.
since
Android 1.0

        return certificateEquals;
    
public java.util.DategetCertificateValid()
Returns the criterion for the validity date of the certificate.

return
the validity date or {@code null} if the date is not to be checked.
since
Android 1.0

        return (certificateValid == null)
                                ? null
                                : (Date) certificateValid.clone();
    
public java.util.SetgetExtendedKeyUsage()
Returns the criterion for the {@literal ExtendedKeyUsage} extension.

return
the set of key usage OIDs, or {@code null} if it's not to be checked.
since
Android 1.0

        return extendedKeyUsage;
    
private byte[]getExtensionValue(java.security.cert.X509Certificate cert, java.lang.String oid)

        try {
            byte[] bytes = cert.getExtensionValue(oid);
            if (bytes == null) {
                return null;
            }
            return (byte[]) ASN1OctetString.getInstance().decode(bytes);
        } catch (IOException e) {
            return null;
        }
    
public javax.security.auth.x500.X500PrincipalgetIssuer()
Returns the issuer that a certificate must match.

return
the issuer that a certificate must match, or {@code null} if the issuer is not to be checked.
since
Android 1.0

        return issuer;
    
public byte[]getIssuerAsBytes()
Returns the issuer that a certificate must match.

return
the distinguished issuer name in ASN.1 DER encoded format, or {@code null} if the issuer is not to be checked.
throws
IOException if encoding the issuer fails.
since
Android 1.0

        if (issuer == null) {
            return null;
        }
        if (issuerBytes == null) {
            issuerBytes = issuer.getEncoded();
        }
        byte[] result = new byte[issuerBytes.length];
        System.arraycopy(issuerBytes, 0, result, 0, issuerBytes.length);
        return result;
    
public java.lang.StringgetIssuerAsString()
Do not use, use {@link #getIssuer()} or {@link #getIssuerAsBytes()} instead. Returns the issuer that a certificate must match in a RFC 2253 format string.

return
the issuer in a RFC 2253 format string, or {@code null} if the issuer is not to be checked.
since
Android 1.0

        if (issuer == null) {
            return null;
        }
        if (issuerName == null) {
            issuerName = issuer.getName();
        }
        return issuerName;
    
public boolean[]getKeyUsage()
Returns the criterion for the {@literal KeyUsage} extension.

return
the boolean array in the format as returned by {@link X509Certificate#getKeyUsage()}, or {@code null} if the key usage is not to be checked.
since
Android 1.0

        if (keyUsage == null) {
            return null;
        }
        boolean[] result = new boolean[keyUsage.length];
        System.arraycopy(keyUsage, 0, result, 0, keyUsage.length);
        return result;
    
public booleangetMatchAllSubjectAltNames()
Returns the flag for the matching behavior for subject alternative names.

The flag indicates whether a certificate must contain all or at least one of the subject alternative names specified by {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName} .

return
{@code true} if a certificate must contain all of the specified subject alternative names, otherwise {@code false}.
since
Android 1.0

        return matchAllNames;
    
public byte[]getNameConstraints()
Returns the criterion for the name constraints.

return
the name constraints or {@code null} if none specified.
see
#setNameConstraints
since
Android 1.0

        return (nameConstraints == null)
            ? null
            : nameConstraints.getEncoded();
    
public java.util.CollectiongetPathToNames()
Returns the criterion for the pathToNames constraint.

The constraint is a collection with an entry for each name to be included in the criterion. The name is specified as a {@code List}, the first entry is an {@code Integer} specifying the name type (0-8), the second entry is a byte array specifying the name in ASN.1 DER encoded form.

return
the pathToNames constraint or {@code null} if none specified.
since
Android 1.0

        if (pathToNames == null) {
            return null;
        }
        ArrayList result = new ArrayList();
        Iterator it = pathToNames.iterator();
        while (it.hasNext()) {
            GeneralName name = (GeneralName) it.next();
            result.add(name.getAsList());
        }
        return result;
    
public java.util.SetgetPolicy()
Returns the criterion for the policy constraint.

The certificate must have at least one of the certificate policy extensions. For an empty set the certificate must have at least some policies in its policy extension.

return
the certificate policy OIDs, an empty set, or {@code null} if not to be checked.
since
Android 1.0

        return policies;
    
public java.util.DategetPrivateKeyValid()
Returns the criterion for the validity date of the private key.

The private key must be valid at the specified date.

return
the validity date or {@code null} if the date is not to be checked.
since
Android 1.0

        if (privateKeyValid != null) {
            return (Date) privateKeyValid.clone();
        }
        return null;
    
public java.math.BigIntegergetSerialNumber()
Returns the serial number that a certificate must match.

return
the serial number to match, or {@code null} if the serial number is not to be checked.
since
Android 1.0

        return serialNumber;
    
public javax.security.auth.x500.X500PrincipalgetSubject()
Returns the subject that a certificate must match.

return
the subject distinguished name, or null if the subject is not to be checked.
since
Android 1.0

        return subject;
    
public java.util.CollectiongetSubjectAlternativeNames()
Returns the criterion for subject alternative names.

the certificate must contain all or at least one of the specified subject alternative names. The behavior is specified by {@link #getMatchAllSubjectAltNames}.

The subject alternative names is a collection with an entry for each name included in the criterion. The name is specified as a {@code List}, the first entry is an {@code Integer} specifying the name type (0-8), the second entry is byte array specifying the name in ASN.1 DER encoded form)

return
the names collection or {@code null} if none specified.
since
Android 1.0

        if (subjectAltNames == null) {
            return null;
        }
        ArrayList result = new ArrayList();
        for (int tag=0; tag<9; tag++) {
            if (subjectAltNames[tag] != null) {
                Integer teg = new Integer(tag);
                for (int name=0; name<subjectAltNames[tag].size(); name++) {
                    Object neim = subjectAltNames[tag].get(name);
                    if (neim instanceof byte[]) {
                        byte[] arr_neim = (byte[]) neim;
                        neim = new byte[arr_neim.length];
                        System.arraycopy(arr_neim, 0, neim, 0, arr_neim.length);
                    }
                    List list = new ArrayList(2);
                    list.add(teg);
                    list.add(neim);
                    result.add(list);
                }
            }
        }
        return result;
    
public byte[]getSubjectAsBytes()
Returns the subject that a certificate must match.

return
the subject distinguished name in ASN.1 DER format, or {@code null} if the subject is not to be checked.
throws
IOException if encoding the subject fails.
since
Android 1.0

        if (subject == null) {
            return null;
        }
        return subject.getEncoded();
    
public java.lang.StringgetSubjectAsString()
Do not use, use {@link #getSubject()} or {@link #getSubjectAsBytes()} instead. Returns the subject that a certificate must match.

return
the subject distinguished name in RFC 2253 format, or {@code null} if the subject is not to be checked.
since
Android 1.0

        if (subject == null) {
            return null;
        }
        return subject.getName();
    
public byte[]getSubjectKeyIdentifier()
Returns the criterion for the {@literal SubjectKeyIdentifier} extension.

return
the subject key identifier or {@code null} if it is not to be checked.
since
Android 1.0

        if (subjectKeyIdentifier == null) {
            return null;
        }
        byte[] res = new byte[subjectKeyIdentifier.length];
        System.arraycopy(subjectKeyIdentifier, 0, res, 0, res.length);
        return res;
    
public java.security.PublicKeygetSubjectPublicKey()
Returns the criterion for the subject public key.

return
the subject public key or {@code null} if the key is not to be checked.
since
Android 1.0

        return subjectPublicKeyImpl;
    
public java.lang.StringgetSubjectPublicKeyAlgID()
Returns the criterion for the subject public key signature algorithm.

return
the OID (object identifier) or the signature algorithm or {@code null} if it's not to be checked.
since
Android 1.0

        return subjectPublicKeyAlgID;
    
public booleanmatch(java.security.cert.Certificate certificate)
Returns whether the specified certificate matches all the criteria collected in this instance.

param
certificate the certificate to check.
return
{@code true} if the certificate matches all the criteria, otherwise {@code false}.
since
Android 1.0

        if (! (certificate instanceof X509Certificate)) {
            return false;
        }

        X509Certificate cert = (X509Certificate) certificate;
        if ((certificateEquals != null) &&
            !certificateEquals.equals(cert)) {
            return false;
        }
        if ((serialNumber != null) &&
            !serialNumber.equals(cert.getSerialNumber())) {
            return false;
        }
        if ((issuer != null) &&
            !issuer.equals(cert.getIssuerX500Principal())) {
            return false;
        }
        if ((subject != null) &&
            !subject.equals(cert.getSubjectX500Principal())) {
            return false;
        }
        if ((subjectKeyIdentifier != null) &&
            !Arrays.equals(subjectKeyIdentifier,
            // Here and later all of the extension OIDs 
            // are taken from rfc 3280 (http://www.ietf.org/rfc/rfc3280.txt)
                           getExtensionValue(cert, "2.5.29.14"))) { //$NON-NLS-1$
            return false;
        }
        if ((authorityKeyIdentifier != null) &&
            !Arrays.equals(authorityKeyIdentifier,
                           getExtensionValue(cert, "2.5.29.35"))) { //$NON-NLS-1$
            return false;
        }
        if (certificateValid != null) {
            try {
                cert.checkValidity(certificateValid);
            } catch(CertificateExpiredException e) {
                return false;
            } catch(CertificateNotYetValidException e) {
                return false;
            }
        }
        if (privateKeyValid != null) {
            try {
                byte[] bytes = getExtensionValue(cert, "2.5.29.16"); //$NON-NLS-1$
                if (bytes == null) {
                    return false;
                }
                PrivateKeyUsagePeriod pkup = (PrivateKeyUsagePeriod) 
                                    PrivateKeyUsagePeriod.ASN1.decode(bytes);
                Date notBefore = pkup.getNotBefore();
                Date notAfter = pkup.getNotAfter();
                if ((notBefore == null) && (notAfter == null)) {
                    return false;
                }
                if ((notBefore != null)
                    && notBefore.compareTo(privateKeyValid) > 0) {
                    return false;
                }
                if ((notAfter != null)
                    && notAfter.compareTo(privateKeyValid) < 0) {
                    return false;
                }
            } catch (IOException e) {
                return false;
            }
        }
        if (subjectPublicKeyAlgID  != null) {
            try {
                byte[] encoding = cert.getPublicKey().getEncoded();
                AlgorithmIdentifier ai = ((SubjectPublicKeyInfo) 
                        SubjectPublicKeyInfo.ASN1.decode(encoding))
                        .getAlgorithmIdentifier();
                if (!subjectPublicKeyAlgID.equals(ai.getAlgorithm())) {
                    return false;
                }
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        if (subjectPublicKey != null) {
            if (!Arrays.equals(subjectPublicKey,
                               cert.getPublicKey().getEncoded())) {
                return false;
            }
        }
        if (keyUsage != null) {
            boolean[] ku = cert.getKeyUsage();
            if (ku != null) {
                int i = 0;
                int min_length = (ku.length < keyUsage.length) ? ku.length
                        : keyUsage.length;
                for (; i < min_length; i++) {
                    if (keyUsage[i] && !ku[i]) {
                        // the specified keyUsage allows,
                        // but certificate does not.
                        return false;
                    }
                }
                for (; i<keyUsage.length; i++) {
                    if (keyUsage[i]) {
                        return false;
                    }
                }
            }
        }
        if (extendedKeyUsage != null) {
            try {
                List keyUsage = cert.getExtendedKeyUsage();
                if (keyUsage != null) {
                    if (!keyUsage.containsAll(extendedKeyUsage)) {
                        return false;
                    }
                }
            } catch (CertificateParsingException e) {
                return false;
            }
        }
        if (pathLen != -1) {
            int p_len = cert.getBasicConstraints();
            if ((pathLen < 0) && (p_len >= 0)) {
                // need end-entity but got CA
                return false;
            }
            if ((pathLen > 0) && (pathLen > p_len)) {
                // allowed _pathLen is small
                return false;
            }
        }
        if (subjectAltNames != null) {
            PASSED:
            try {
                byte[] bytes = getExtensionValue(cert, "2.5.29.17"); //$NON-NLS-1$
                if (bytes == null) {
                    return false;
                }
                List sans = ((GeneralNames) GeneralNames.ASN1.decode(bytes))
                            .getNames();
                if ((sans == null) || (sans.size() == 0)) {
                    return false;
                }
                boolean[][] map = new boolean[9][];
                // initialize the check map
                for (int i=0; i<9; i++) {
                    map[i] = (subjectAltNames[i] == null)
                                ? new boolean[0]
                                : new boolean[subjectAltNames[i].size()];
                }
                Iterator it = sans.iterator();
                while (it.hasNext()) {
                    GeneralName name = (GeneralName) it.next();
                    int tag = name.getTag();
                    for (int i=0; i<map[tag].length; i++) {
                        if (((GeneralName) subjectAltNames[tag].get(i))
                                                            .equals(name)) {
                            if (!matchAllNames) {
                                break PASSED;
                            }
                            map[tag][i] = true;
                        }
                    }
                }
                if (!matchAllNames) {
                    // there was not any match
                    return false;
                }
                // else check the map
                for (int tag=0; tag<9; tag++) {
                    for (int name=0; name<map[tag].length; name++) {
                        if (!map[tag][name]) {
                            return false;
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }
        if (nameConstraints != null) {
            if (!nameConstraints.isAcceptable(cert)) {
                return false;
            }
        }
        if (policies != null) {
            byte[] bytes = getExtensionValue(cert, "2.5.29.32"); //$NON-NLS-1$
            if (bytes == null) {
                return false;
            }
            if (policies.size() == 0) {
                // if certificate has such extension than it has at least
                // one policy in it.
                return true;
            }
            PASSED:
            try {
                List policyInformations = ((CertificatePolicies) 
                        CertificatePolicies.ASN1.decode(bytes))
                        .getPolicyInformations();
                Iterator it = policyInformations.iterator();
                while (it.hasNext()) {
                    if (policies.contains(((PolicyInformation) it.next())
                                          .getPolicyIdentifier())) {
                        break PASSED;
                    }
                }
                return false;
            } catch (IOException e) {
                // the extension is invalid
                return false;
            }
        }
        if (pathToNames != null) {
            byte[] bytes = getExtensionValue(cert, "2.5.29.30"); //$NON-NLS-1$
            if (bytes != null) {
                NameConstraints nameConstraints;
                try {
                    nameConstraints =
                        (NameConstraints) NameConstraints.ASN1.decode(bytes);
                } catch (IOException e) {
                    // the extension is invalid;
                    return false;
                }
                if (!nameConstraints.isAcceptable(pathToNames)) {
                    return false;
                }
            }
        }
        return true;
    
public voidsetAuthorityKeyIdentifier(byte[] authorityKeyIdentifier)
Sets the criterion for the {@literal AuthorityKeyIdentifier} extension.

param
authorityKeyIdentifier the authority key identifier, or {@code null} to disable this check.
since
Android 1.0

        if (authorityKeyIdentifier == null) {
            this.authorityKeyIdentifier = null;
            return;
        }
        this.authorityKeyIdentifier = new byte[authorityKeyIdentifier.length];
        System.arraycopy(authorityKeyIdentifier, 0,
                         this.authorityKeyIdentifier, 0,
                         authorityKeyIdentifier.length);
    
public voidsetBasicConstraints(int pathLen)
Sets the criterion for the basic constraints extension.

A value greater than or equal to zero indicates that a certificate must include a basic constraints extension with a path length of a least that value. A value of {@code -2} indicates that only end-entity certificates are accepted. A value of {@code -1} indicates that no check is done.

param
pathLen the value specifying the criterion.
since
Android 1.0
throws
IllegalArgumentException if {@code pathLen} is less than {@code -2}.

        if (pathLen < -2) {
            throw new IllegalArgumentException(Messages.getString("security.58")); //$NON-NLS-1$
        }
        this.pathLen = pathLen;
    
public voidsetCertificate(java.security.cert.X509Certificate certificate)
Sets the certificate that a matching certificate must be equal to.

param
certificate the certificate to match, or null to not check this criteria.
since
Android 1.0

        certificateEquals = certificate;
    
public voidsetCertificateValid(java.util.Date certificateValid)
Sets the criterion for the validity date of the certificate.

The certificate must be valid at the specified date.

param
certificateValid the validity date or {@code null} to not check the date.
since
Android 1.0

        this.certificateValid = (certificateValid == null)
                                ? null
                                : (Date) certificateValid.clone();
    
public voidsetExtendedKeyUsage(java.util.Set keyUsage)
Sets the criterion for the {@literal ExtendedKeyUsage} extension.

param
keyUsage the set of key usage OIDs, or {@code null} to not check it.
throws
IOException if one of the OIDs is invalid.
since
Android 1.0

        extendedKeyUsage = null;
        if ((keyUsage == null) || (keyUsage.size() == 0)) {
            return;
        }
        HashSet key_u = new HashSet();
        Iterator it = keyUsage.iterator();
        while (it.hasNext()) {
            String usage = (String) it.next();
            checkOID(usage);
            key_u.add(usage);
        }
        extendedKeyUsage = Collections.unmodifiableSet(key_u);
    
public voidsetIssuer(byte[] issuerDN)
Sets the issuer that a certificate must match.

param
issuerDN the distinguished issuer name in ASN.1 DER encoded format, or {@code null} to not check the issuer.
throws
IOException if decoding the issuer fail.
since
Android 1.0

        if (issuerDN == null) {
            issuer = null;
            return;
        }
        try {
            issuer = new X500Principal(issuerDN);
            this.issuerName = null;
            this.issuerBytes = new byte[issuerDN.length];
            System.arraycopy(issuerDN, 0, this.issuerBytes, 0, issuerDN.length);
        } catch (IllegalArgumentException e) {
            throw new IOException(e.getMessage());
        }
    
public voidsetIssuer(javax.security.auth.x500.X500Principal issuer)
Sets the issuer that a certificate must match.

param
issuer the issuer to match, or {@code null} if the issuer is not to be checked.
since
Android 1.0

        this.issuer = issuer;
        this.issuerName = null;
        this.issuerBytes = null;
    
public voidsetIssuer(java.lang.String issuerName)
Do not use, use {@link #getIssuer()} or {@link #getIssuerAsBytes()} instead. Sets the issuer that a certificate must match.

param
issuerName the issuer in a RFC 2253 format string, or {@code null} to not check the issuer.
throws
IOException if parsing the issuer fails.
since
Android 1.0

        if (issuerName == null) {
            this.issuer = null;
            this.issuerName = null;
            this.issuerBytes = null;
            return;
        }
        try {
            this.issuer = new X500Principal(issuerName);
            this.issuerName = issuerName;
            this.issuerBytes = null;
        } catch (IllegalArgumentException e) {
            throw new IOException(e.getMessage());
        }
    
public voidsetKeyUsage(boolean[] keyUsage)
Sets the criterion for the {@literal KeyUsage} extension.

param
keyUsage the boolean array in the format as returned by {@link X509Certificate#getKeyUsage()}, or {@code null} to not check the key usage.
since
Android 1.0

        if (keyUsage == null) {
            this.keyUsage = null;
            return;
        }
        this.keyUsage = new boolean[keyUsage.length];
        System.arraycopy(keyUsage, 0, this.keyUsage, 0, keyUsage.length);
    
public voidsetMatchAllSubjectAltNames(boolean matchAllNames)
Sets the flag for the matching behavior for subject alternative names.

The flag indicates whether a certificate must contain all or at least one of the subject alternative names specified by {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName} .

param
matchAllNames {@code true} if a certificate must contain all of the specified subject alternative names, otherwise {@code false}.
since
Android 1.0

        this.matchAllNames = matchAllNames;
    
public voidsetNameConstraints(byte[] bytes)
Sets the criterion for the name constraints.

The certificate must constraint subject and subject alternative names that match the specified name constraints.

The name constraints in ASN.1:

NameConstraints ::= SEQUENCE {
permittedSubtrees [0] GeneralSubtrees OPTIONAL,
excludedSubtrees [1] GeneralSubtrees OPTIONAL }

GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree

GeneralSubtree ::= SEQUENCE {
base GeneralName,
minimum [0] BaseDistance DEFAULT 0,
maximum [1] BaseDistance OPTIONAL }

BaseDistance ::= INTEGER (0..MAX)

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}

param
bytes the name constraints in ASN.1 DER encoded format, or null to not check any constraints.
throws
IOException if decoding the name constraints fail.
since
Android 1.0

        this.nameConstraints = (bytes == null)
            ? null
            : (NameConstraints) NameConstraints.ASN1.decode(bytes);
    
public voidsetPathToNames(java.util.Collection names)
Sets the criterion for the pathToNames constraint.

This allows to specify the complete set of names, a certificate's name constraints must permit.

The specified parameter {@code names} is a collection with an entry for each name to be included in the criterion. The name is specified as a {@code List}, the first entry must be an {@code Integer} specifying the name type (0-8), the second entry must be a {@code String} or a byte array specifying the name (in string or ASN.1 DER encoded form)

param
names the names collection or {@code null} to not perform this check.
throws
IOException if decoding fails.
since
Android 1.0

        pathToNames = null;
        if ((names == null) || (names.size() == 0)) {
            return;
        }
        Iterator it = names.iterator();
        while (it.hasNext()) {
            List name = (List) it.next();
            int tag = ((Integer) name.get(0)).intValue();
            Object value = name.get(1);
            if (value instanceof String) {
                addPathToName(tag, (String) value);
            } else if (value instanceof byte[]) {
                addPathToName(tag, (byte[]) value);
            } else {
                throw new IOException(Messages.getString("security.57")); //$NON-NLS-1$
            }
        }
    
public voidsetPolicy(java.util.Set policies)
Sets the criterion for the policy constraint.

The certificate must have at least one of the specified certificate policy extensions. For an empty set the certificate must have at least some policies in its policy extension.

param
policies the certificate policy OIDs, an empty set, or {@code null} to not perform this check.
throws
IOException if parsing the specified OIDs fails.
since
Android 1.0

        if (policies == null) {
            this.policies = null;
            return;
        }
        HashSet pols = new HashSet(policies.size());
        Iterator it = policies.iterator();
        while (it.hasNext()) {
            String certPolicyId = (String) it.next();
            checkOID(certPolicyId);
            pols.add(certPolicyId);
        }
        this.policies = Collections.unmodifiableSet(pols);
    
public voidsetPrivateKeyValid(java.util.Date privateKeyValid)
Sets the criterion for the validity date of the private key.

The private key must be valid at the specified date.

param
privateKeyValid the validity date or {@code null} to not check the date.
since
Android 1.0

        if (privateKeyValid == null) {
            this.privateKeyValid = null;
            return;
        }
        this.privateKeyValid = (Date) privateKeyValid.clone();
    
public voidsetSerialNumber(java.math.BigInteger serialNumber)
Sets the serial number that a certificate must match.

param
serialNumber the serial number to match, or {@code null} to not check the serial number.
since
Android 1.0

        this.serialNumber = serialNumber;
    
public voidsetSubject(javax.security.auth.x500.X500Principal subject)
Set the subject that a certificate must match.

param
subject the subject distinguished name or {@code null} to not check the subject.
since
Android 1.0

        this.subject = subject;
    
public voidsetSubject(java.lang.String subjectDN)
Do not use, use {@link #setSubject(byte[])} or {@link #setSubject(X500Principal)} instead. Returns the subject that a certificate must match.

param
subjectDN the subject distinguished name in RFC 2253 format or {@code null} to not check the subject.
throws
IOException if decoding the subject fails.
since
Android 1.0

        if (subjectDN == null) {
            subject = null;
            return;
        }
        try {
            subject = new X500Principal(subjectDN);
        } catch (IllegalArgumentException e) {
            throw new IOException(e.getMessage());
        }
    
public voidsetSubject(byte[] subjectDN)
Sets the subject that a certificate must match.

param
subjectDN the subject distinguished name in ASN.1 DER format, or {@code null} to not check the subject.
throws
IOException if decoding the subject fails.
since
Android 1.0

        if (subjectDN == null) {
            subject = null;
            return;
        }
        try {
            subject = new X500Principal(subjectDN);
        } catch (IllegalArgumentException e) {
            throw new IOException(e.getMessage());
        }
    
public voidsetSubjectAlternativeNames(java.util.Collection names)
Sets the criterion for subject alternative names.

the certificate must contain all or at least one of the specified subject alternative names. The behavior is specified by {@link #getMatchAllSubjectAltNames}.

The specified parameter {@code names} is a collection with an entry for each name to be included in the criterion. The name is specified as a {@code List}, the first entry must be an {@code Integer} specifying the name type (0-8), the second entry must be a {@code String} or a byte array specifying the name (in string or ASN.1 DER encoded form)

param
names the names collection or {@code null} to not perform this check.
throws
IOException if the decoding of a name fails.
since
Android 1.0

        subjectAltNames = null;
        if ((names == null) || (names.size() == 0)) {
            return;
        }
        Iterator it = names.iterator();
        while (it.hasNext()) {
            List name = (List) it.next();
            int tag = ((Integer) name.get(0)).intValue();
            Object value = name.get(1);
            if (value instanceof String) {
                addSubjectAlternativeName(tag, (String) value);
            } else if (value instanceof byte[]) {
                addSubjectAlternativeName(tag, (byte[]) value);
            } else {
                throw new IOException(Messages.getString("security.57")); //$NON-NLS-1$
            }
        }
    
public voidsetSubjectKeyIdentifier(byte[] subjectKeyIdentifier)
Sets the criterion for the {@literal SubjectKeyIdentifier} extension.

The {@code subjectKeyIdentifier} should be a single DER encoded value.

param
subjectKeyIdentifier the subject key identifier or {@code null} to disable this check.
since
Android 1.0

        if (subjectKeyIdentifier == null) {
            this.subjectKeyIdentifier = null;
            return;
        }
        this.subjectKeyIdentifier = new byte[subjectKeyIdentifier.length];
        System.arraycopy(subjectKeyIdentifier, 0, this.subjectKeyIdentifier, 0,
                         subjectKeyIdentifier.length);
    
public voidsetSubjectPublicKey(java.security.PublicKey key)
Sets the criterion for the subject public key.

param
key the subject public key or {@code null} to not check the key.
since
Android 1.0

        subjectPublicKey = (key == null) ? null : key.getEncoded();
        subjectPublicKeyImpl = key;
    
public voidsetSubjectPublicKey(byte[] key)
Sets the criterion for the subject public key.

param
key the subject public key in ASN.1 DER encoded format or {@code null} to not check the key.
throws
IOException if decoding the the public key fails.
since
Android 1.0

        if (key == null) {
            subjectPublicKey = null;
            subjectPublicKeyImpl = null;
            return;
        }
        subjectPublicKey = new byte[key.length];
        System.arraycopy(key, 0, subjectPublicKey, 0, key.length);
        subjectPublicKeyImpl = 
            ((SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1.decode(key))
            .getPublicKey();
    
public voidsetSubjectPublicKeyAlgID(java.lang.String oid)
Sets the criterion for the subject public key signature algorithm.

The certificate must contain a subject public key with the algorithm specified.

param
oid the OID (object identifier) of the signature algorithm or {@code null} to not check the OID.
throws
IOException if the specified object identifier is invalid.
since
Android 1.0

        if (oid == null) {
            subjectPublicKeyAlgID = null;
            return;
        }
        checkOID(oid);
        subjectPublicKeyAlgID = oid;
    
public java.lang.StringtoString()
Returns a string representation of this {@code X509CertSelector} instance.

return
a string representation of this {@code X509CertSelector} instance.
since
Android 1.0

        // For convenient reading of the string representation
        // all of the fields named according to the rfc 3280
        // (http://www.ietf.org/rfc/rfc3280.txt).

        StringBuffer result = new StringBuffer();
        result.append("X509CertSelector: \n["); //$NON-NLS-1$
        if (this.certificateEquals != null) {
            result.append("\n  certificateEquals: " + certificateEquals); //$NON-NLS-1$
        }
        if (this.serialNumber != null) {
            //FIXME: needs DRL's BigInteger.toString implementation
            //result.append("\n  serialNumber: " + serialNumber);
        }
        if (this.issuer != null) {
            result.append("\n  issuer: " + issuer); //$NON-NLS-1$
        }
        if (this.subject != null) {
            result.append("\n  subject: " + subject); //$NON-NLS-1$
        }
        if (this.subjectKeyIdentifier != null) {
            result.append("\n  subjectKeyIdentifier: " //$NON-NLS-1$
                    + getBytesAsString(subjectKeyIdentifier));
        }
        if (this.authorityKeyIdentifier != null) {
            result.append("\n  authorityKeyIdentifier: " //$NON-NLS-1$
                    + getBytesAsString(authorityKeyIdentifier));
        }
        if (this.certificateValid != null) {
            result.append("\n  certificateValid: " + certificateValid); //$NON-NLS-1$
        }
        if (this.subjectPublicKeyAlgID != null) {
            result.append("\n  subjectPublicKeyAlgID: " //$NON-NLS-1$
                    + subjectPublicKeyAlgID);
        }
        if (this.privateKeyValid != null) {
            result.append("\n  privateKeyValid: " + privateKeyValid); //$NON-NLS-1$
        }
        if (this.subjectPublicKey != null) {
            result.append("\n  subjectPublicKey: " //$NON-NLS-1$
                    + getBytesAsString(subjectPublicKey));
        }
        if (this.keyUsage != null) {
            result.append("\n  keyUsage: \n  ["); //$NON-NLS-1$
            String[] kuNames = new String[] {
                "digitalSignature", "nonRepudiation", "keyEncipherment", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                "dataEncipherment", "keyAgreement", "keyCertSign", "cRLSign", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                "encipherOnly", "decipherOnly" //$NON-NLS-1$ //$NON-NLS-2$
            };
            for (int i=0; i<9; i++) {
                if (keyUsage[i]) {
                    result.append("\n    " + kuNames[i]); //$NON-NLS-1$
                }
            }
            result.append("\n  ]"); //$NON-NLS-1$
        }
        if (this.extendedKeyUsage != null) {
            result.append("\n  extendedKeyUsage: " //$NON-NLS-1$
                    + extendedKeyUsage.toString());
        }
        result.append("\n  matchAllNames: " + matchAllNames); //$NON-NLS-1$
        result.append("\n  pathLen: " + pathLen); //$NON-NLS-1$
        if (this.subjectAltNames != null) {
            result.append("\n  subjectAltNames:  \n  ["); //$NON-NLS-1$
            for (int i=0; i<9; i++) {
                List names = this.subjectAltNames[i];
                if (names != null) {
                    int size = names.size();
                    for (int j=0; j<size; j++) {
                        result.append("\n    " //$NON-NLS-1$
                            + ((GeneralName)names.get(j)).toString());
                    }
                }
            }
            result.append("\n  ]"); //$NON-NLS-1$
        }
        if (this.nameConstraints != null) {
        }
        if (this.policies != null) {
            result.append("\n  policies: " + policies.toString()); //$NON-NLS-1$
        }
        if (this.pathToNames != null) {
            result.append("\n  pathToNames:  \n  ["); //$NON-NLS-1$
            int size = pathToNames.size();
            for (int i = 0; i < size; i++) {
                result.append("\n    " //$NON-NLS-1$
                    + ((GeneralName)pathToNames.get(i)).toString());
            }
        }
        result.append("\n]"); //$NON-NLS-1$
        return result.toString();