001 /* 002 * $HeadURL: http://juliusdavies.ca/svn/not-yet-commons-ssl/tags/commons-ssl-0.3.11/src/java/org/apache/commons/ssl/KeyMaterial.java $ 003 * $Revision: 138 $ 004 * $Date: 2008-03-03 23:50:07 -0800 (Mon, 03 Mar 2008) $ 005 * 006 * ==================================================================== 007 * Licensed to the Apache Software Foundation (ASF) under one 008 * or more contributor license agreements. See the NOTICE file 009 * distributed with this work for additional information 010 * regarding copyright ownership. The ASF licenses this file 011 * to you under the Apache License, Version 2.0 (the 012 * "License"); you may not use this file except in compliance 013 * with the License. You may obtain a copy of the License at 014 * 015 * http://www.apache.org/licenses/LICENSE-2.0 016 * 017 * Unless required by applicable law or agreed to in writing, 018 * software distributed under the License is distributed on an 019 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 020 * KIND, either express or implied. See the License for the 021 * specific language governing permissions and limitations 022 * under the License. 023 * ==================================================================== 024 * 025 * This software consists of voluntary contributions made by many 026 * individuals on behalf of the Apache Software Foundation. For more 027 * information on the Apache Software Foundation, please see 028 * <http://www.apache.org/>. 029 * 030 */ 031 032 package org.apache.commons.ssl; 033 034 import java.io.File; 035 import java.io.FileInputStream; 036 import java.io.IOException; 037 import java.io.InputStream; 038 import java.net.URL; 039 import java.security.GeneralSecurityException; 040 import java.security.KeyStore; 041 import java.security.KeyStoreException; 042 import java.security.cert.Certificate; 043 import java.security.cert.CertificateEncodingException; 044 import java.security.cert.X509Certificate; 045 import java.util.Collections; 046 import java.util.Enumeration; 047 import java.util.Iterator; 048 import java.util.LinkedList; 049 import java.util.List; 050 051 /** 052 * @author Credit Union Central of British Columbia 053 * @author <a href="http://www.cucbc.com/">www.cucbc.com</a> 054 * @author <a href="mailto:juliusdavies@cucbc.com">juliusdavies@cucbc.com</a> 055 * @since 27-Feb-2006 056 */ 057 public class KeyMaterial extends TrustMaterial { 058 private final Object keyManagerFactory; 059 private final List aliases; 060 private final List associatedChains; 061 062 public KeyMaterial(InputStream jks, char[] password) 063 throws GeneralSecurityException, IOException { 064 this(Util.streamToBytes(jks), password); 065 } 066 067 public KeyMaterial(InputStream jks, char[] jksPass, char[] keyPass) 068 throws GeneralSecurityException, IOException { 069 this(Util.streamToBytes(jks), jksPass, keyPass); 070 } 071 072 public KeyMaterial(InputStream jks, InputStream key, char[] password) 073 throws GeneralSecurityException, IOException { 074 this(jks != null ? Util.streamToBytes(jks) : null, 075 key != null ? Util.streamToBytes(key) : null, 076 password); 077 } 078 079 public KeyMaterial(InputStream jks, InputStream key, char[] jksPass, 080 char[] keyPass) 081 throws GeneralSecurityException, IOException { 082 this(jks != null ? Util.streamToBytes(jks) : null, 083 key != null ? Util.streamToBytes(key) : null, 084 jksPass, keyPass); 085 } 086 087 public KeyMaterial(String pathToJksFile, char[] password) 088 throws GeneralSecurityException, IOException { 089 this(new File(pathToJksFile), password); 090 } 091 092 public KeyMaterial(String pathToJksFile, char[] jksPass, char[] keyPass) 093 throws GeneralSecurityException, IOException { 094 this(new File(pathToJksFile), jksPass, keyPass); 095 } 096 097 public KeyMaterial(String pathToCerts, String pathToKey, char[] password) 098 throws GeneralSecurityException, IOException { 099 this(pathToCerts != null ? new File(pathToCerts) : null, 100 pathToKey != null ? new File(pathToKey) : null, 101 password); 102 } 103 104 public KeyMaterial(String pathToCerts, String pathToKey, char[] jksPass, 105 char[] keyPass) 106 throws GeneralSecurityException, IOException { 107 this(pathToCerts != null ? new File(pathToCerts) : null, 108 pathToKey != null ? new File(pathToKey) : null, 109 jksPass, keyPass); 110 } 111 112 public KeyMaterial(File jksFile, char[] password) 113 throws GeneralSecurityException, IOException { 114 this(new FileInputStream(jksFile), password); 115 } 116 117 public KeyMaterial(File jksFile, char[] jksPass, char[] keyPass) 118 throws GeneralSecurityException, IOException { 119 this(new FileInputStream(jksFile), jksPass, keyPass); 120 } 121 122 public KeyMaterial(File certsFile, File keyFile, char[] password) 123 throws GeneralSecurityException, IOException { 124 this(certsFile != null ? new FileInputStream(certsFile) : null, 125 keyFile != null ? new FileInputStream(keyFile) : null, 126 password); 127 } 128 129 public KeyMaterial(File certsFile, File keyFile, char[] jksPass, 130 char[] keyPass) 131 throws GeneralSecurityException, IOException { 132 this(certsFile != null ? new FileInputStream(certsFile) : null, 133 keyFile != null ? new FileInputStream(keyFile) : null, 134 jksPass, keyPass); 135 } 136 137 public KeyMaterial(URL urlToJKS, char[] password) 138 throws GeneralSecurityException, IOException { 139 this(urlToJKS.openStream(), password); 140 } 141 142 public KeyMaterial(URL urlToJKS, char[] jksPass, char[] keyPass) 143 throws GeneralSecurityException, IOException { 144 this(urlToJKS.openStream(), jksPass, keyPass); 145 } 146 147 public KeyMaterial(URL urlToCerts, URL urlToKey, char[] password) 148 throws GeneralSecurityException, IOException { 149 this(urlToCerts.openStream(), urlToKey.openStream(), password); 150 } 151 152 public KeyMaterial(URL urlToCerts, URL urlToKey, char[] jksPass, 153 char[] keyPass) 154 throws GeneralSecurityException, IOException { 155 this(urlToCerts.openStream(), urlToKey.openStream(), jksPass, keyPass); 156 } 157 158 public KeyMaterial(byte[] jks, char[] password) 159 throws GeneralSecurityException, IOException { 160 this(jks, (byte[]) null, password); 161 } 162 163 public KeyMaterial(byte[] jks, char[] jksPass, char[] keyPass) 164 throws GeneralSecurityException, IOException { 165 this(jks, null, jksPass, keyPass); 166 } 167 168 public KeyMaterial(byte[] jksOrCerts, byte[] key, char[] password) 169 throws GeneralSecurityException, IOException { 170 this(jksOrCerts, key, password, password); 171 } 172 173 174 public KeyMaterial(byte[] jksOrCerts, byte[] key, char[] jksPass, 175 char[] keyPass) 176 throws GeneralSecurityException, IOException { 177 // We're not a simple trust type, so set "simpleTrustType" value to 0. 178 // Only TRUST_ALL and TRUST_THIS_JVM are simple trust types. 179 super(KeyStoreBuilder.build(jksOrCerts, key, jksPass, keyPass), 0); 180 KeyStore ks = getKeyStore(); 181 Enumeration en = ks.aliases(); 182 List myAliases = new LinkedList(); 183 List myChains = new LinkedList(); 184 while (en.hasMoreElements()) { 185 X509Certificate[] c; // chain 186 String alias = (String) en.nextElement(); 187 if (ks.isKeyEntry(alias)) { 188 try { 189 ks.getKey(alias, keyPass); 190 // No Exception thrown, so we're good! 191 myAliases.add(alias); 192 Certificate[] chain = ks.getCertificateChain(alias); 193 if (chain != null) { 194 c = Certificates.x509ifyChain(chain); 195 // Cleanup chain to remove any spurious entries. 196 if (c != null) { 197 X509Certificate l = c[0]; // The leaf node. 198 c = X509CertificateChainBuilder.buildPath(l, c); 199 } 200 myChains.add(c); 201 } else { 202 throw new KeyStoreException("Could not find KeyMaterial's associated certificate chain with alis=[" + alias + "]"); 203 } 204 205 } catch (GeneralSecurityException gse) { 206 // oh well, we can't use that KeyStore alias. 207 } 208 } 209 } 210 if (myAliases.isEmpty()) { 211 throw new KeyStoreException("KeyMaterial provided does not contain any keys!"); 212 } 213 this.aliases = Collections.unmodifiableList(myAliases); 214 this.associatedChains = Collections.unmodifiableList(myChains); 215 this.keyManagerFactory = JavaImpl.newKeyManagerFactory(ks, keyPass); 216 } 217 218 public Object[] getKeyManagers() { 219 return JavaImpl.getKeyManagers(keyManagerFactory); 220 } 221 222 public List getAssociatedCertificateChains() { 223 return associatedChains; 224 } 225 226 public KeyStore getKeyStore() { 227 return super.getKeyStore(); 228 } 229 230 public List getAliases() { 231 return aliases; 232 } 233 234 public static void main(String[] args) throws Exception { 235 if (args.length < 2) { 236 System.out.println("Usage1: java org.apache.commons.ssl.KeyMaterial [password] [pkcs12 or jks]"); 237 System.out.println("Usage2: java org.apache.commons.ssl.KeyMaterial [password] [private-key] [cert-chain]"); 238 System.exit(1); 239 } 240 char[] jksPass = args[0].toCharArray(); 241 char[] keyPass = jksPass; 242 String path1 = args[1]; 243 String path2 = null; 244 if (args.length >= 3) { 245 path2 = args[2]; 246 } 247 if (args.length >= 4) { 248 keyPass = args[3].toCharArray(); 249 } else if (path2 != null) { 250 File f = new File(path2); 251 if (!f.exists()) { 252 // Hmmm... maybe it's a password. 253 keyPass = path2.toCharArray(); 254 path2 = null; 255 } 256 } 257 258 KeyMaterial km = new KeyMaterial(path1, path2, jksPass, keyPass); 259 System.out.println(km); 260 } 261 262 public String toString() { 263 List chains = getAssociatedCertificateChains(); 264 List aliases = getAliases(); 265 Iterator it = chains.iterator(); 266 Iterator aliasesIt = aliases.iterator(); 267 StringBuffer buf = new StringBuffer(8192); 268 while (it.hasNext()) { 269 X509Certificate[] certs = (X509Certificate[]) it.next(); 270 String alias = (String) aliasesIt.next(); 271 buf.append("Alias: "); 272 buf.append(alias); 273 buf.append('\n'); 274 if (certs != null) { 275 for (int i = 0; i < certs.length; i++) { 276 buf.append(Certificates.toString(certs[i])); 277 try { 278 buf.append(Certificates.toPEMString(certs[i])); 279 } 280 catch (CertificateEncodingException cee) { 281 buf.append(cee.toString()); 282 buf.append('\n'); 283 } 284 } 285 } 286 } 287 return buf.toString(); 288 } 289 }