1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations; 24 25 import java.security.Key; 26 import java.security.KeyStore; 27 import java.security.KeyStoreException; 28 import java.security.PrivateKey; 29 import java.security.PublicKey; 30 import java.security.cert.Certificate; 31 import java.security.cert.CertificateEncodingException; 32 import java.security.cert.X509Certificate; 33 import java.util.Arrays; 34 import java.util.Enumeration; 35 import javax.crypto.SecretKey; 36 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; 37 import com.sun.org.apache.xml.internal.security.keys.content.X509Data; 38 import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509Certificate; 39 import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509IssuerSerial; 40 import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509SKI; 41 import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509SubjectName; 42 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException; 43 import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi; 44 import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; 45 import com.sun.org.apache.xml.internal.security.utils.Constants; 46 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 47 import org.w3c.dom.Element; 48 49 /** 50 * Resolves a PrivateKey within a KeyStore based on the KeyInfo hints. 51 * For X509Data hints, the certificate associated with the private key entry must match. 52 * For a KeyName hint, the KeyName must match the alias of a PrivateKey entry within the KeyStore. 53 */ 54 public class PrivateKeyResolver extends KeyResolverSpi { 55 56 private static final com.sun.org.slf4j.internal.Logger LOG = 57 com.sun.org.slf4j.internal.LoggerFactory.getLogger(PrivateKeyResolver.class); 58 59 private KeyStore keyStore; 60 private char[] password; 61 62 /** 63 * Constructor. 64 */ PrivateKeyResolver(KeyStore keyStore, char[] password)65 public PrivateKeyResolver(KeyStore keyStore, char[] password) { 66 this.keyStore = keyStore; 67 this.password = password; 68 } 69 70 /** 71 * This method returns whether the KeyResolverSpi is able to perform the requested action. 72 * 73 * @param element 74 * @param baseURI 75 * @param storage 76 * @return whether the KeyResolverSpi is able to perform the requested action. 77 */ engineCanResolve(Element element, String baseURI, StorageResolver storage)78 public boolean engineCanResolve(Element element, String baseURI, StorageResolver storage) { 79 if (XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_X509DATA) 80 || XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYNAME)) { 81 return true; 82 } 83 84 return false; 85 } 86 87 /** 88 * Method engineLookupAndResolvePublicKey 89 * 90 * @param element 91 * @param baseURI 92 * @param storage 93 * @return null if no {@link PublicKey} could be obtained 94 * @throws KeyResolverException 95 */ engineLookupAndResolvePublicKey( Element element, String baseURI, StorageResolver storage )96 public PublicKey engineLookupAndResolvePublicKey( 97 Element element, String baseURI, StorageResolver storage 98 ) throws KeyResolverException { 99 return null; 100 } 101 102 /** 103 * Method engineResolveX509Certificate 104 * {@inheritDoc} 105 * @param element 106 * @param baseURI 107 * @param storage 108 * @throws KeyResolverException 109 */ engineLookupResolveX509Certificate( Element element, String baseURI, StorageResolver storage )110 public X509Certificate engineLookupResolveX509Certificate( 111 Element element, String baseURI, StorageResolver storage 112 ) throws KeyResolverException { 113 return null; 114 } 115 116 /** 117 * Method engineResolveSecretKey 118 * 119 * @param element 120 * @param baseURI 121 * @param storage 122 * @return resolved SecretKey key or null if no {@link SecretKey} could be obtained 123 * 124 * @throws KeyResolverException 125 */ engineResolveSecretKey( Element element, String baseURI, StorageResolver storage )126 public SecretKey engineResolveSecretKey( 127 Element element, String baseURI, StorageResolver storage 128 ) throws KeyResolverException { 129 return null; 130 } 131 132 /** 133 * Method engineResolvePrivateKey 134 * {@inheritDoc} 135 * @param element 136 * @param baseURI 137 * @param storage 138 * @return resolved PrivateKey key or null if no {@link PrivateKey} could be obtained 139 * @throws KeyResolverException 140 */ engineLookupAndResolvePrivateKey( Element element, String baseURI, StorageResolver storage )141 public PrivateKey engineLookupAndResolvePrivateKey( 142 Element element, String baseURI, StorageResolver storage 143 ) throws KeyResolverException { 144 LOG.debug("Can I resolve {}?", element.getTagName()); 145 146 if (XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_X509DATA)) { 147 PrivateKey privKey = resolveX509Data(element, baseURI); 148 if (privKey != null) { 149 return privKey; 150 } 151 } else if (XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYNAME)) { 152 LOG.debug("Can I resolve KeyName?"); 153 String keyName = element.getFirstChild().getNodeValue(); 154 155 try { 156 Key key = keyStore.getKey(keyName, password); 157 if (key instanceof PrivateKey) { 158 return (PrivateKey) key; 159 } 160 } catch (Exception e) { 161 LOG.debug("Cannot recover the key", e); 162 } 163 } 164 165 LOG.debug("I can't"); 166 return null; 167 } 168 resolveX509Data(Element element, String baseURI)169 private PrivateKey resolveX509Data(Element element, String baseURI) { 170 LOG.debug("Can I resolve X509Data?"); 171 172 try { 173 X509Data x509Data = new X509Data(element, baseURI); 174 175 int len = x509Data.lengthSKI(); 176 for (int i = 0; i < len; i++) { 177 XMLX509SKI x509SKI = x509Data.itemSKI(i); 178 PrivateKey privKey = resolveX509SKI(x509SKI); 179 if (privKey != null) { 180 return privKey; 181 } 182 } 183 184 len = x509Data.lengthIssuerSerial(); 185 for (int i = 0; i < len; i++) { 186 XMLX509IssuerSerial x509Serial = x509Data.itemIssuerSerial(i); 187 PrivateKey privKey = resolveX509IssuerSerial(x509Serial); 188 if (privKey != null) { 189 return privKey; 190 } 191 } 192 193 len = x509Data.lengthSubjectName(); 194 for (int i = 0; i < len; i++) { 195 XMLX509SubjectName x509SubjectName = x509Data.itemSubjectName(i); 196 PrivateKey privKey = resolveX509SubjectName(x509SubjectName); 197 if (privKey != null) { 198 return privKey; 199 } 200 } 201 202 len = x509Data.lengthCertificate(); 203 for (int i = 0; i < len; i++) { 204 XMLX509Certificate x509Cert = x509Data.itemCertificate(i); 205 PrivateKey privKey = resolveX509Certificate(x509Cert); 206 if (privKey != null) { 207 return privKey; 208 } 209 } 210 } catch (XMLSecurityException e) { 211 LOG.debug("XMLSecurityException", e); 212 } catch (KeyStoreException e) { 213 LOG.debug("KeyStoreException", e); 214 } 215 216 return null; 217 } 218 219 /* 220 * Search for a private key entry in the KeyStore with the same Subject Key Identifier 221 */ resolveX509SKI(XMLX509SKI x509SKI)222 private PrivateKey resolveX509SKI(XMLX509SKI x509SKI) throws XMLSecurityException, KeyStoreException { 223 LOG.debug("Can I resolve X509SKI?"); 224 225 Enumeration<String> aliases = keyStore.aliases(); 226 while (aliases.hasMoreElements()) { 227 String alias = aliases.nextElement(); 228 if (keyStore.isKeyEntry(alias)) { 229 230 Certificate cert = keyStore.getCertificate(alias); 231 if (cert instanceof X509Certificate) { 232 XMLX509SKI certSKI = new XMLX509SKI(x509SKI.getDocument(), (X509Certificate) cert); 233 234 if (certSKI.equals(x509SKI)) { 235 LOG.debug("match !!! "); 236 237 try { 238 Key key = keyStore.getKey(alias, password); 239 if (key instanceof PrivateKey) { 240 return (PrivateKey) key; 241 } 242 } catch (Exception e) { 243 LOG.debug("Cannot recover the key", e); 244 // Keep searching 245 } 246 } 247 } 248 } 249 } 250 251 return null; 252 } 253 254 /* 255 * Search for a private key entry in the KeyStore with the same Issuer/Serial Number pair. 256 */ resolveX509IssuerSerial(XMLX509IssuerSerial x509Serial)257 private PrivateKey resolveX509IssuerSerial(XMLX509IssuerSerial x509Serial) throws KeyStoreException { 258 LOG.debug("Can I resolve X509IssuerSerial?"); 259 260 Enumeration<String> aliases = keyStore.aliases(); 261 while (aliases.hasMoreElements()) { 262 String alias = aliases.nextElement(); 263 if (keyStore.isKeyEntry(alias)) { 264 265 Certificate cert = keyStore.getCertificate(alias); 266 if (cert instanceof X509Certificate) { 267 XMLX509IssuerSerial certSerial = 268 new XMLX509IssuerSerial(x509Serial.getDocument(), (X509Certificate) cert); 269 270 if (certSerial.equals(x509Serial)) { 271 LOG.debug("match !!! "); 272 273 try { 274 Key key = keyStore.getKey(alias, password); 275 if (key instanceof PrivateKey) { 276 return (PrivateKey) key; 277 } 278 } catch (Exception e) { 279 LOG.debug("Cannot recover the key", e); 280 // Keep searching 281 } 282 } 283 } 284 } 285 } 286 287 return null; 288 } 289 290 /* 291 * Search for a private key entry in the KeyStore with the same Subject Name. 292 */ resolveX509SubjectName(XMLX509SubjectName x509SubjectName)293 private PrivateKey resolveX509SubjectName(XMLX509SubjectName x509SubjectName) throws KeyStoreException { 294 LOG.debug("Can I resolve X509SubjectName?"); 295 296 Enumeration<String> aliases = keyStore.aliases(); 297 while (aliases.hasMoreElements()) { 298 String alias = aliases.nextElement(); 299 if (keyStore.isKeyEntry(alias)) { 300 301 Certificate cert = keyStore.getCertificate(alias); 302 if (cert instanceof X509Certificate) { 303 XMLX509SubjectName certSN = 304 new XMLX509SubjectName(x509SubjectName.getDocument(), (X509Certificate) cert); 305 306 if (certSN.equals(x509SubjectName)) { 307 LOG.debug("match !!! "); 308 309 try { 310 Key key = keyStore.getKey(alias, password); 311 if (key instanceof PrivateKey) { 312 return (PrivateKey) key; 313 } 314 } catch (Exception e) { 315 LOG.debug("Cannot recover the key", e); 316 // Keep searching 317 } 318 } 319 } 320 } 321 } 322 323 return null; 324 } 325 326 /* 327 * Search for a private key entry in the KeyStore with the same Certificate. 328 */ resolveX509Certificate( XMLX509Certificate x509Cert )329 private PrivateKey resolveX509Certificate( 330 XMLX509Certificate x509Cert 331 ) throws XMLSecurityException, KeyStoreException { 332 LOG.debug("Can I resolve X509Certificate?"); 333 byte[] x509CertBytes = x509Cert.getCertificateBytes(); 334 335 Enumeration<String> aliases = keyStore.aliases(); 336 while (aliases.hasMoreElements()) { 337 String alias = aliases.nextElement(); 338 if (keyStore.isKeyEntry(alias)) { 339 340 Certificate cert = keyStore.getCertificate(alias); 341 if (cert instanceof X509Certificate) { 342 byte[] certBytes = null; 343 344 try { 345 certBytes = cert.getEncoded(); 346 } catch (CertificateEncodingException e1) { 347 LOG.debug("Cannot recover the key", e1); 348 } 349 350 if (certBytes != null && Arrays.equals(certBytes, x509CertBytes)) { 351 LOG.debug("match !!! "); 352 353 try { 354 Key key = keyStore.getKey(alias, password); 355 if (key instanceof PrivateKey) { 356 return (PrivateKey) key; 357 } 358 } 359 catch (Exception e) { 360 LOG.debug("Cannot recover the key", e); 361 // Keep searching 362 } 363 } 364 } 365 } 366 } 367 368 return null; 369 } 370 } 371