/* * Copyright (c) 2005, 2014, 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. * * 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.
*/
/** * A <code>KeySelector</code> that returns {@link PublicKey}s. If the * selector is created as trusted, it only returns public keys of trusted * {@link X509Certificate}s stored in a {@link KeyStore}. Otherwise, it * returns trusted or untrusted public keys (it doesn't care as long * as it finds one). * * <p>This <code>KeySelector</code> uses the specified <code>KeyStore</code> * to find a trusted <code>X509Certificate</code> that matches information * specified in the {@link KeyInfo} passed to the {@link #select} method. * The public key from the first match is returned. If no match, * <code>null</code> is returned. See the <code>select</code> method for more * information. * * @author Sean Mullan
*/ class X509KeySelector extends KeySelector {
/** * Creates a trusted <code>X509KeySelector</code>. * * @param keyStore the keystore * @throws KeyStoreException if the keystore has not been initialized * @throws NullPointerException if <code>keyStore</code> is * <code>null</code>
*/
X509KeySelector(KeyStore keyStore) throws KeyStoreException { this(keyStore, true);
}
X509KeySelector(KeyStore keyStore, boolean trusted) throws KeyStoreException { if (keyStore == null) { thrownew NullPointerException("keyStore is null");
} this.trusted = trusted; this.ks = keyStore; // test to see if KeyStore has been initialized this.ks.size();
}
/** * Finds a key from the keystore satisfying the specified constraints. * * <p>This method compares data contained in {@link KeyInfo} entries * with information stored in the <code>KeyStore</code>. The implementation * iterates over the KeyInfo types and returns the first {@link PublicKey} * of an X509Certificate in the keystore that is compatible with the * specified AlgorithmMethod according to the following rules for each * keyinfo type: * * X509Data X509Certificate: if it contains a <code>KeyUsage</code> * extension that asserts the <code>digitalSignature</code> bit and * matches an <code>X509Certificate</code> in the <code>KeyStore</code>. * X509Data X509IssuerSerial: if the serial number and issuer DN match an * <code>X509Certificate</code> in the <code>KeyStore</code>. * X509Data X509SubjectName: if the subject DN matches an * <code>X509Certificate</code> in the <code>KeyStore</code>. * X509Data X509SKI: if the subject key identifier matches an * <code>X509Certificate</code> in the <code>KeyStore</code>. * KeyName: if the keyname matches an alias in the <code>KeyStore</code>. * RetrievalMethod: supports rawX509Certificate and X509Data types. If * rawX509Certificate type, it must match an <code>X509Certificate</code> * in the <code>KeyStore</code>. * * @param keyInfo a <code>KeyInfo</code> (may be <code>null</code>) * @param purpose the key's purpose * @param method the algorithm method that this key is to be used for. * Only keys that are compatible with the algorithm and meet the * constraints of the specified algorithm should be returned. * @param an <code>XMLCryptoContext</code> that may contain additional * useful information for finding an appropriate key * @return a key selector result * @throws KeySelectorException if an exceptional condition occurs while * attempting to find a key. Note that an inability to find a key is not * considered an exception (<code>null</code> should be * returned in that case). However, an error condition (ex: network * communications failure) that prevented the <code>KeySelector</code> * from finding a potential key should be considered an exception. * @throws ClassCastException if the data type of <code>method</code> * is not supported by this key selector
*/ public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose, AlgorithmMethod method,
XMLCryptoContext context) throws KeySelectorException {
SignatureMethod sm = (SignatureMethod) method;
try { // return null if keyinfo is null or keystore is empty if (keyInfo == null || ks.size() == 0) { returnnew SimpleKeySelectorResult(null);
}
// return null since no match could be found returnnew SimpleKeySelectorResult(null);
}
/** * Searches the specified keystore for a certificate that matches the * criteria specified in the CertSelector. * * @return a KeySelectorResult containing the cert's public key if there * is a match; otherwise null
*/ private KeySelectorResult keyStoreSelect(CertSelector cs) throws KeyStoreException {
Enumeration<String> aliases = ks.aliases(); while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Certificate cert = ks.getCertificate(alias); if (cert != null && cs.match(cert)) { returnnew SimpleKeySelectorResult(cert.getPublicKey());
}
} returnnull;
}
/** * Searches the specified keystore for a certificate that matches the * specified X509Certificate and contains a public key that is compatible * with the specified SignatureMethod. * * @return a KeySelectorResult containing the cert's public key if there * is a match; otherwise null
*/ private KeySelectorResult certSelect(X509Certificate xcert,
SignatureMethod sm) throws KeyStoreException { // skip non-signer certs boolean[] keyUsage = xcert.getKeyUsage(); if (keyUsage != null && keyUsage[0] == false) { returnnull;
}
String alias = ks.getCertificateAlias(xcert); if (alias != null) {
PublicKey pk = ks.getCertificate(alias).getPublicKey(); // make sure algorithm is compatible with method if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) { returnnew SimpleKeySelectorResult(pk);
}
} returnnull;
}
/** * Returns an OID of a public-key algorithm compatible with the specified * signature algorithm URI.
*/ private String getPKAlgorithmOID(String algURI) { if (algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) { return"1.2.840.10040.4.1";
} elseif (algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) { return"1.2.840.113549.1.1";
} else { returnnull;
}
}
/** * A simple KeySelectorResult containing a public key.
*/ privatestaticclass SimpleKeySelectorResult implements KeySelectorResult { privatefinal Key key;
SimpleKeySelectorResult(Key key) { this.key = key; } public Key getKey() { return key; }
}
/** * Checks if a JCA/JCE public key algorithm name is compatible with * the specified signature algorithm URI.
*/ //@@@FIXME: this should also work for key types other than DSA/RSA privateboolean algEquals(String algURI, String algName) { if (algName.equalsIgnoreCase("DSA") &&
algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) { returntrue;
} elseif (algName.equalsIgnoreCase("RSA") &&
algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) { returntrue;
} else { returnfalse;
}
}
/** * Searches the specified keystore for a certificate that matches an * entry of the specified X509Data and contains a public key that is * compatible with the specified SignatureMethod. * * @return a KeySelectorResult containing the cert's public key if there * is a match; otherwise null
*/ private KeySelectorResult x509DataSelect(X509Data xd, SignatureMethod sm) throws KeyStoreException, KeySelectorException {
// convert signature algorithm to compatible public-key alg OID
String algOID = getPKAlgorithmOID(sm.getAlgorithm());
X509CertSelector subjectcs = new X509CertSelector(); try {
subjectcs.setSubjectPublicKeyAlgID(algOID);
} catch (IOException ioe) { thrownew KeySelectorException(ioe);
}
Collection<X509Certificate> certs = new ArrayList<>();
for (Object o : xd.getContent()) { // check X509IssuerSerial if (o instanceof X509IssuerSerial) {
X509IssuerSerial xis = (X509IssuerSerial) o; try {
subjectcs.setSerialNumber(xis.getSerialNumber());
String issuer = new X500Principal(xis.getIssuerName()).getName(); // strip off newline if (issuer.endsWith("\n")) {
issuer = new String
(issuer.toCharArray(), 0, issuer.length()-1);
}
subjectcs.setIssuer(issuer);
} catch (IOException ioe) { thrownew KeySelectorException(ioe);
} // check X509SubjectName
} elseif (o instanceof String) {
String sn = (String) o; try {
String subject = new X500Principal(sn).getName(); // strip off newline if (subject.endsWith("\n")) {
subject = new String
(subject.toCharArray(), 0, subject.length()-1);
}
subjectcs.setSubject(subject);
} catch (IOException ioe) { thrownew KeySelectorException(ioe);
} // check X509SKI
} elseif (o instanceofbyte[]) { byte[] ski = (byte[]) o; // DER-encode ski - required by X509CertSelector byte[] encodedSki = newbyte[ski.length+2];
encodedSki[0] = 0x04; // OCTET STRING tag value
encodedSki[1] = (byte) ski.length; // length
System.arraycopy(ski, 0, encodedSki, 2, ski.length);
subjectcs.setSubjectKeyIdentifier(encodedSki);
} elseif (o instanceof X509Certificate) {
certs.add((X509Certificate)o); // check X509CRL // not supported: should use CertPath API
} else { // skip all other entries continue;
}
}
KeySelectorResult ksr = keyStoreSelect(subjectcs); if (ksr != null) { return ksr;
} if (!certs.isEmpty() && !trusted) { // try to find public key in certs in X509Data for (X509Certificate cert : certs) { if (subjectcs.match(cert)) { returnnew SimpleKeySelectorResult(cert.getPublicKey());
}
}
} returnnull;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.27 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.