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 final KeyStore keyStore; 60 private final 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 /** {@inheritDoc} */ 71 @Override engineCanResolve(Element element, String baseURI, StorageResolver storage)72 protected boolean engineCanResolve(Element element, String baseURI, StorageResolver storage) { 73 return XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_X509DATA) 74 || XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYNAME); 75 } 76 77 /** {@inheritDoc} */ 78 @Override engineResolvePublicKey( Element element, String baseURI, StorageResolver storage, boolean secureValidation )79 protected PublicKey engineResolvePublicKey( 80 Element element, String baseURI, StorageResolver storage, boolean secureValidation 81 ) throws KeyResolverException { 82 return null; 83 } 84 85 /** {@inheritDoc} */ 86 @Override engineResolveX509Certificate( Element element, String baseURI, StorageResolver storage, boolean secureValidation )87 protected X509Certificate engineResolveX509Certificate( 88 Element element, String baseURI, StorageResolver storage, boolean secureValidation 89 ) throws KeyResolverException { 90 return null; 91 } 92 93 /** {@inheritDoc} */ 94 @Override engineResolveSecretKey( Element element, String baseURI, StorageResolver storage, boolean secureValidation )95 protected SecretKey engineResolveSecretKey( 96 Element element, String baseURI, StorageResolver storage, boolean secureValidation 97 ) throws KeyResolverException { 98 return null; 99 } 100 101 /** {@inheritDoc} */ 102 @Override engineResolvePrivateKey( Element element, String baseURI, StorageResolver storage, boolean secureValidation )103 public PrivateKey engineResolvePrivateKey( 104 Element element, String baseURI, StorageResolver storage, boolean secureValidation 105 ) throws KeyResolverException { 106 107 if (XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_X509DATA)) { 108 PrivateKey privKey = resolveX509Data(element, baseURI); 109 if (privKey != null) { 110 return privKey; 111 } 112 } else if (XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYNAME)) { 113 LOG.debug("Can I resolve KeyName?"); 114 String keyName = element.getFirstChild().getNodeValue(); 115 116 try { 117 Key key = keyStore.getKey(keyName, password); 118 if (key instanceof PrivateKey) { 119 return (PrivateKey) key; 120 } 121 } catch (Exception e) { 122 LOG.debug("Cannot recover the key", e); 123 } 124 } 125 126 return null; 127 } 128 resolveX509Data(Element element, String baseURI)129 private PrivateKey resolveX509Data(Element element, String baseURI) { 130 LOG.debug("Can I resolve X509Data?"); 131 132 try { 133 X509Data x509Data = new X509Data(element, baseURI); 134 135 int len = x509Data.lengthSKI(); 136 for (int i = 0; i < len; i++) { 137 XMLX509SKI x509SKI = x509Data.itemSKI(i); 138 PrivateKey privKey = resolveX509SKI(x509SKI); 139 if (privKey != null) { 140 return privKey; 141 } 142 } 143 144 len = x509Data.lengthIssuerSerial(); 145 for (int i = 0; i < len; i++) { 146 XMLX509IssuerSerial x509Serial = x509Data.itemIssuerSerial(i); 147 PrivateKey privKey = resolveX509IssuerSerial(x509Serial); 148 if (privKey != null) { 149 return privKey; 150 } 151 } 152 153 len = x509Data.lengthSubjectName(); 154 for (int i = 0; i < len; i++) { 155 XMLX509SubjectName x509SubjectName = x509Data.itemSubjectName(i); 156 PrivateKey privKey = resolveX509SubjectName(x509SubjectName); 157 if (privKey != null) { 158 return privKey; 159 } 160 } 161 162 len = x509Data.lengthCertificate(); 163 for (int i = 0; i < len; i++) { 164 XMLX509Certificate x509Cert = x509Data.itemCertificate(i); 165 PrivateKey privKey = resolveX509Certificate(x509Cert); 166 if (privKey != null) { 167 return privKey; 168 } 169 } 170 } catch (XMLSecurityException e) { 171 LOG.debug("XMLSecurityException", e); 172 } catch (KeyStoreException e) { 173 LOG.debug("KeyStoreException", e); 174 } 175 176 return null; 177 } 178 179 /* 180 * Search for a private key entry in the KeyStore with the same Subject Key Identifier 181 */ resolveX509SKI(XMLX509SKI x509SKI)182 private PrivateKey resolveX509SKI(XMLX509SKI x509SKI) throws XMLSecurityException, KeyStoreException { 183 LOG.debug("Can I resolve X509SKI?"); 184 185 Enumeration<String> aliases = keyStore.aliases(); 186 while (aliases.hasMoreElements()) { 187 String alias = aliases.nextElement(); 188 if (keyStore.isKeyEntry(alias)) { 189 190 Certificate cert = keyStore.getCertificate(alias); 191 if (cert instanceof X509Certificate) { 192 XMLX509SKI certSKI = new XMLX509SKI(x509SKI.getDocument(), (X509Certificate) cert); 193 194 if (certSKI.equals(x509SKI)) { 195 LOG.debug("match !!! "); 196 197 try { 198 Key key = keyStore.getKey(alias, password); 199 if (key instanceof PrivateKey) { 200 return (PrivateKey) key; 201 } 202 } catch (Exception e) { 203 LOG.debug("Cannot recover the key", e); 204 // Keep searching 205 } 206 } 207 } 208 } 209 } 210 211 return null; 212 } 213 214 /* 215 * Search for a private key entry in the KeyStore with the same Issuer/Serial Number pair. 216 */ resolveX509IssuerSerial(XMLX509IssuerSerial x509Serial)217 private PrivateKey resolveX509IssuerSerial(XMLX509IssuerSerial x509Serial) throws KeyStoreException { 218 LOG.debug("Can I resolve X509IssuerSerial?"); 219 220 Enumeration<String> aliases = keyStore.aliases(); 221 while (aliases.hasMoreElements()) { 222 String alias = aliases.nextElement(); 223 if (keyStore.isKeyEntry(alias)) { 224 225 Certificate cert = keyStore.getCertificate(alias); 226 if (cert instanceof X509Certificate) { 227 XMLX509IssuerSerial certSerial = 228 new XMLX509IssuerSerial(x509Serial.getDocument(), (X509Certificate) cert); 229 230 if (certSerial.equals(x509Serial)) { 231 LOG.debug("match !!! "); 232 233 try { 234 Key key = keyStore.getKey(alias, password); 235 if (key instanceof PrivateKey) { 236 return (PrivateKey) key; 237 } 238 } catch (Exception e) { 239 LOG.debug("Cannot recover the key", e); 240 // Keep searching 241 } 242 } 243 } 244 } 245 } 246 247 return null; 248 } 249 250 /* 251 * Search for a private key entry in the KeyStore with the same Subject Name. 252 */ resolveX509SubjectName(XMLX509SubjectName x509SubjectName)253 private PrivateKey resolveX509SubjectName(XMLX509SubjectName x509SubjectName) throws KeyStoreException { 254 LOG.debug("Can I resolve X509SubjectName?"); 255 256 Enumeration<String> aliases = keyStore.aliases(); 257 while (aliases.hasMoreElements()) { 258 String alias = aliases.nextElement(); 259 if (keyStore.isKeyEntry(alias)) { 260 261 Certificate cert = keyStore.getCertificate(alias); 262 if (cert instanceof X509Certificate) { 263 XMLX509SubjectName certSN = 264 new XMLX509SubjectName(x509SubjectName.getDocument(), (X509Certificate) cert); 265 266 if (certSN.equals(x509SubjectName)) { 267 LOG.debug("match !!! "); 268 269 try { 270 Key key = keyStore.getKey(alias, password); 271 if (key instanceof PrivateKey) { 272 return (PrivateKey) key; 273 } 274 } catch (Exception e) { 275 LOG.debug("Cannot recover the key", e); 276 // Keep searching 277 } 278 } 279 } 280 } 281 } 282 283 return null; 284 } 285 286 /* 287 * Search for a private key entry in the KeyStore with the same Certificate. 288 */ resolveX509Certificate( XMLX509Certificate x509Cert )289 private PrivateKey resolveX509Certificate( 290 XMLX509Certificate x509Cert 291 ) throws XMLSecurityException, KeyStoreException { 292 LOG.debug("Can I resolve X509Certificate?"); 293 byte[] x509CertBytes = x509Cert.getCertificateBytes(); 294 295 Enumeration<String> aliases = keyStore.aliases(); 296 while (aliases.hasMoreElements()) { 297 String alias = aliases.nextElement(); 298 if (keyStore.isKeyEntry(alias)) { 299 300 Certificate cert = keyStore.getCertificate(alias); 301 if (cert instanceof X509Certificate) { 302 byte[] certBytes = null; 303 304 try { 305 certBytes = cert.getEncoded(); 306 } catch (CertificateEncodingException e1) { 307 LOG.debug("Cannot recover the key", e1); 308 } 309 310 if (certBytes != null && Arrays.equals(certBytes, x509CertBytes)) { 311 LOG.debug("match !!! "); 312 313 try { 314 Key key = keyStore.getKey(alias, password); 315 if (key instanceof PrivateKey) { 316 return (PrivateKey) key; 317 } 318 } 319 catch (Exception e) { 320 LOG.debug("Cannot recover the key", e); 321 // Keep searching 322 } 323 } 324 } 325 } 326 } 327 328 return null; 329 } 330 } 331