jdk/test/javax/xml/crypto/dsig/X509KeySelector.java
author tbell
Thu, 23 Apr 2009 21:32:44 -0700
changeset 2636 3d0e25588136
parent 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Merge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
import java.io.InputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
import java.security.Key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.security.KeyStore;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.security.KeyStoreException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.security.PublicKey;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.security.cert.Certificate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.security.cert.CertificateFactory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.security.cert.CertSelector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.security.cert.X509Certificate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.security.cert.X509CertSelector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import javax.security.auth.x500.X500Principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import javax.xml.crypto.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import javax.xml.crypto.dsig.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import javax.xml.crypto.dom.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import javax.xml.crypto.dsig.keyinfo.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import org.jcp.xml.dsig.internal.dom.DOMRetrievalMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * A <code>KeySelector</code> that returns {@link PublicKey}s. If the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * selector is created as trusted, it only returns public keys of trusted
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * {@link X509Certificate}s stored in a {@link KeyStore}. Otherwise, it
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * returns trusted or untrusted public keys (it doesn't care as long
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * as it finds one).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * <p>This <code>KeySelector</code> uses the specified <code>KeyStore</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * to find a trusted <code>X509Certificate</code> that matches information
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * specified in the {@link KeyInfo} passed to the {@link #select} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * The public key from the first match is returned. If no match,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * <code>null</code> is returned. See the <code>select</code> method for more
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * information.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * @author Sean Mullan
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
class X509KeySelector extends KeySelector {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    private KeyStore ks;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    private boolean trusted = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
     * Creates a trusted <code>X509KeySelector</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
     * @param keyStore the keystore
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
     * @throws KeyStoreException if the keystore has not been initialized
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
     * @throws NullPointerException if <code>keyStore</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
     *    <code>null</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    X509KeySelector(KeyStore keyStore) throws KeyStoreException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
        this(keyStore, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    X509KeySelector(KeyStore keyStore, boolean trusted)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
        throws KeyStoreException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
        if (keyStore == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
            throw new NullPointerException("keyStore is null");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        this.trusted = trusted;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        this.ks = keyStore;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        // test to see if KeyStore has been initialized
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
        this.ks.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
     * Finds a key from the keystore satisfying the specified constraints.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * <p>This method compares data contained in {@link KeyInfo} entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     * with information stored in the <code>KeyStore</code>. The implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     * iterates over the KeyInfo types and returns the first {@link PublicKey}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
     * of an X509Certificate in the keystore that is compatible with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
     * specified AlgorithmMethod according to the following rules for each
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
     * keyinfo type:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * X509Data X509Certificate: if it contains a <code>KeyUsage</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     *   extension that asserts the <code>digitalSignature</code> bit and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     *   matches an <code>X509Certificate</code> in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * X509Data X509IssuerSerial: if the serial number and issuer DN match an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     *    <code>X509Certificate</code> in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * X509Data X509SubjectName: if the subject DN matches an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     *    <code>X509Certificate</code> in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     * X509Data X509SKI: if the subject key identifier matches an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
     *    <code>X509Certificate</code> in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     * KeyName: if the keyname matches an alias in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     * RetrievalMethod: supports rawX509Certificate and X509Data types. If
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     *    rawX509Certificate type, it must match an <code>X509Certificate</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
     *    in the <code>KeyStore</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * @param keyInfo a <code>KeyInfo</code> (may be <code>null</code>)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * @param purpose the key's purpose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * @param method the algorithm method that this key is to be used for.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     *    Only keys that are compatible with the algorithm and meet the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     *    constraints of the specified algorithm should be returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * @param an <code>XMLCryptoContext</code> that may contain additional
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     *    useful information for finding an appropriate key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     * @return a key selector result
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
     * @throws KeySelectorException if an exceptional condition occurs while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     *    attempting to find a key. Note that an inability to find a key is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     *    considered an exception (<code>null</code> should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     *    returned in that case). However, an error condition (ex: network
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     *    communications failure) that prevented the <code>KeySelector</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     *    from finding a potential key should be considered an exception.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * @throws ClassCastException if the data type of <code>method</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     *    is not supported by this key selector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    public KeySelectorResult select(KeyInfo keyInfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        KeySelector.Purpose purpose, AlgorithmMethod method,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        XMLCryptoContext context) throws KeySelectorException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        SignatureMethod sm = (SignatureMethod) method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            // return null if keyinfo is null or keystore is empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            if (keyInfo == null || ks.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                return new SimpleKeySelectorResult(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            // Iterate through KeyInfo types
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            Iterator i = keyInfo.getContent().iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
            while (i.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
                XMLStructure kiType = (XMLStructure) i.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                // check X509Data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                if (kiType instanceof X509Data) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                    X509Data xd = (X509Data) kiType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                    KeySelectorResult ksr = x509DataSelect(xd, sm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                    if (ksr != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
                        return ksr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                // check KeyName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                } else if (kiType instanceof KeyName) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                    KeyName kn = (KeyName) kiType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                    Certificate cert = ks.getCertificate(kn.getName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                    if (cert != null && algEquals(sm.getAlgorithm(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                        cert.getPublicKey().getAlgorithm())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                        return new SimpleKeySelectorResult(cert.getPublicKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                // check RetrievalMethod
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                } else if (kiType instanceof RetrievalMethod) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                    RetrievalMethod rm = (RetrievalMethod) kiType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                        KeySelectorResult ksr = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                        if (rm.getType().equals
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                            (X509Data.RAW_X509_CERTIFICATE_TYPE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                            OctetStreamData data = (OctetStreamData)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                                rm.dereference(context);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                            CertificateFactory cf =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
                                CertificateFactory.getInstance("X.509");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                            X509Certificate cert = (X509Certificate)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
                                cf.generateCertificate(data.getOctetStream());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
                            ksr = certSelect(cert, sm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
                        } else if (rm.getType().equals(X509Data.TYPE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                            X509Data xd = (X509Data) ((DOMRetrievalMethod) rm).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                                dereferenceAsXMLStructure(context);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                            ksr = x509DataSelect(xd, sm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                            // skip; keyinfo type is not supported
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                            continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                        if (ksr != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                            return ksr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                    } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                        throw new KeySelectorException(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        } catch (KeyStoreException kse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            // throw exception if keystore is uninitialized
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            throw new KeySelectorException(kse);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        // return null since no match could be found
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        return new SimpleKeySelectorResult(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
     * Searches the specified keystore for a certificate that matches the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
     * criteria specified in the CertSelector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
     * @return a KeySelectorResult containing the cert's public key if there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     *   is a match; otherwise null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
    private KeySelectorResult keyStoreSelect(CertSelector cs)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        throws KeyStoreException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        Enumeration aliases = ks.aliases();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        while (aliases.hasMoreElements()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
            String alias = (String) aliases.nextElement();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            Certificate cert = ks.getCertificate(alias);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            if (cert != null && cs.match(cert)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                return new SimpleKeySelectorResult(cert.getPublicKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
     * Searches the specified keystore for a certificate that matches the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
     * specified X509Certificate and contains a public key that is compatible
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     * with the specified SignatureMethod.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     * @return a KeySelectorResult containing the cert's public key if there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     *   is a match; otherwise null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    private KeySelectorResult certSelect(X509Certificate xcert,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        SignatureMethod sm) throws KeyStoreException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
        // skip non-signer certs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        boolean[] keyUsage = xcert.getKeyUsage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        if (keyUsage != null && keyUsage[0] == false) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        String alias = ks.getCertificateAlias(xcert);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        if (alias != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            PublicKey pk = ks.getCertificate(alias).getPublicKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            // make sure algorithm is compatible with method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                return new SimpleKeySelectorResult(pk);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * Returns an OID of a public-key algorithm compatible with the specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * signature algorithm URI.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    private String getPKAlgorithmOID(String algURI) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        if (algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            return "1.2.840.10040.4.1";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        } else if (algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
            return "1.2.840.113549.1.1";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     * A simple KeySelectorResult containing a public key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    private static class SimpleKeySelectorResult implements KeySelectorResult {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        private final Key key;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        SimpleKeySelectorResult(Key key) { this.key = key; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        public Key getKey() { return key; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * Checks if a JCA/JCE public key algorithm name is compatible with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * the specified signature algorithm URI.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    //@@@FIXME: this should also work for key types other than DSA/RSA
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    private boolean algEquals(String algURI, String algName) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        if (algName.equalsIgnoreCase("DSA") &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        } else if (algName.equalsIgnoreCase("RSA") &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * Searches the specified keystore for a certificate that matches an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * entry of the specified X509Data and contains a public key that is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * compatible with the specified SignatureMethod.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * @return a KeySelectorResult containing the cert's public key if there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     *   is a match; otherwise null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    private KeySelectorResult x509DataSelect(X509Data xd, SignatureMethod sm)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        throws KeyStoreException, KeySelectorException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        // convert signature algorithm to compatible public-key alg OID
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        String algOID = getPKAlgorithmOID(sm.getAlgorithm());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        X509CertSelector subjectcs = new X509CertSelector();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            subjectcs.setSubjectPublicKeyAlgID(algOID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        } catch (IOException ioe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            throw new KeySelectorException(ioe);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        Collection certs = new ArrayList();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        Iterator xi = xd.getContent().iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        while (xi.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            Object o = xi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            // check X509IssuerSerial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            if (o instanceof X509IssuerSerial) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                X509IssuerSerial xis = (X509IssuerSerial) o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                    subjectcs.setSerialNumber(xis.getSerialNumber());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
                    String issuer = new X500Principal(xis.getIssuerName()).getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                    // strip off newline
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                    if (issuer.endsWith("\n")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                        issuer = new String
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                            (issuer.toCharArray(), 0, issuer.length()-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                    subjectcs.setIssuer(issuer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                } catch (IOException ioe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                    throw new KeySelectorException(ioe);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
            // check X509SubjectName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
            } else if (o instanceof String) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                String sn = (String) o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                    String subject = new X500Principal(sn).getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                    // strip off newline
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                    if (subject.endsWith("\n")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                        subject = new String
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                            (subject.toCharArray(), 0, subject.length()-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                    subjectcs.setSubject(subject);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                } catch (IOException ioe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                    throw new KeySelectorException(ioe);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
            // check X509SKI
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            } else if (o instanceof byte[]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                byte[] ski = (byte[]) o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                // DER-encode ski - required by X509CertSelector
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                byte[] encodedSki = new byte[ski.length+2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                encodedSki[0] = 0x04; // OCTET STRING tag value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                encodedSki[1] = (byte) ski.length; // length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                System.arraycopy(ski, 0, encodedSki, 2, ski.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
                subjectcs.setSubjectKeyIdentifier(encodedSki);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
            } else if (o instanceof X509Certificate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                certs.add((X509Certificate) o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
            // check X509CRL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            // not supported: should use CertPath API
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
                // skip all other entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
        KeySelectorResult ksr = keyStoreSelect(subjectcs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        if (ksr != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            return ksr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        if (!certs.isEmpty() && !trusted) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            // try to find public key in certs in X509Data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            Iterator i = certs.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            while (i.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                X509Certificate cert = (X509Certificate) i.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                if (subjectcs.match(cert)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                    return new SimpleKeySelectorResult(cert.getPublicKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
}