1 13 14 package org.ejbca.core.protocol.xkms.client; 15 16 import java.security.KeyStore ; 17 import java.security.PrivateKey ; 18 import java.security.cert.Certificate ; 19 import java.security.cert.CertificateException ; 20 import java.security.cert.X509Certificate ; 21 import java.util.ArrayList ; 22 import java.util.Collection ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 26 import javax.xml.bind.JAXBElement; 27 28 import org.ejbca.core.protocol.xkms.common.XKMSConstants; 29 import org.ejbca.core.protocol.xkms.common.XKMSUtil; 30 import org.ejbca.ui.cli.ErrorAdminCommandException; 31 import org.ejbca.ui.cli.IAdminCommand; 32 import org.ejbca.ui.cli.IllegalAdminCommandException; 33 import org.ejbca.util.CertTools; 34 import org.ejbca.util.KeyTools; 35 import org.w3._2000._09.xmldsig_.KeyInfoType; 36 import org.w3._2000._09.xmldsig_.X509DataType; 37 import org.w3._2002._03.xkms_.KeyBindingType; 38 import org.w3._2002._03.xkms_.ObjectFactory; 39 import org.w3._2002._03.xkms_.RecoverRequestType; 40 import org.w3._2002._03.xkms_.RecoverResultType; 41 42 43 44 45 46 52 public class RecoverCommand extends XKMSCLIBaseCommand implements IAdminCommand{ 53 54 private ObjectFactory xKMSObjectFactory = new ObjectFactory(); 55 private org.w3._2000._09.xmldsig_.ObjectFactory sigFactory = new org.w3._2000._09.xmldsig_.ObjectFactory(); 56 57 private static final int ARG_CERT = 1; 58 private static final int ARG_CERTENCODING = 2; 59 private static final int ARG_PASSWORD = 3; 60 private static final int ARG_ENCODING = 4; 61 private static final int ARG_OUTPUTPATH = 5; 62 63 64 65 70 public RecoverCommand(String [] args) { 71 super(args); 72 } 73 74 80 public void execute() throws IllegalAdminCommandException, ErrorAdminCommandException { 81 82 try { 83 84 if(args.length < 5 || args.length > 6){ 85 usage(); 86 System.exit(-1); 87 } 88 89 String certEncoding = getCertEncoding(args[ARG_CERTENCODING]); 90 X509Certificate orgCert = getCert(args[ARG_CERT],certEncoding); 91 String password = args[ARG_PASSWORD]; 92 93 String encoding = useEncoding(args[ARG_ENCODING]); 94 95 String outputPath = ""; 96 if(args.length >= ARG_OUTPUTPATH +1){ 97 if(args[ARG_OUTPUTPATH] != null){ 98 outputPath = args[ARG_OUTPUTPATH] + "/"; 99 } 100 } 101 102 String reqId = genId(); 103 RecoverRequestType recoverRequestType = xKMSObjectFactory.createRecoverRequestType(); 104 recoverRequestType.setId(reqId); 105 recoverRequestType.getRespondWith().add(XKMSConstants.RESPONDWITH_X509CHAIN); 106 recoverRequestType.getRespondWith().add(XKMSConstants.RESPONDWITH_PRIVATEKEY); 107 108 X509DataType x509DataType = sigFactory.createX509DataType(); 109 x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName().add(sigFactory.createX509DataTypeX509Certificate(orgCert.getEncoded())); 110 KeyInfoType keyInfoType = sigFactory.createKeyInfoType(); 111 keyInfoType.getContent().add(sigFactory.createX509Data(x509DataType)); 112 113 String keyBindingId = "_" + orgCert.getSerialNumber().toString(); 114 KeyBindingType keyBindingType = xKMSObjectFactory.createKeyBindingType(); 115 keyBindingType.setKeyInfo(keyInfoType); 116 keyBindingType.setId(keyBindingId); 117 recoverRequestType.setRecoverKeyBinding(keyBindingType); 118 119 120 121 RecoverResultType recoverResultType = getXKMSInvoker().recover(recoverRequestType, clientCert, privateKey, password, keyBindingId); 122 123 124 if(recoverResultType.getResultMajor().equals(XKMSConstants.RESULTMAJOR_SUCCESS) && 125 recoverResultType.getResultMinor() == null){ 126 127 if(recoverResultType.getKeyBinding().size() >0){ 128 KeyBindingType keyBinding = recoverResultType.getKeyBinding().get(0); 129 List certs = getCertsFromKeyBinding(keyBinding); 130 131 X509Certificate userCert = getUserCert(certs); 132 certs.remove(userCert); 133 134 if(recoverResultType.getPrivateKey() != null){ 135 PrivateKey serverKey = XKMSUtil.getPrivateKeyFromEncryptedXML(recoverResultType.getPrivateKey(), password); 136 createKeyStore(userCert, certs, serverKey,password,encoding,outputPath); 137 }else{ 138 getPrintStream().println("Error: Response didn't contain any private key"); 139 System.exit(-1); 140 } 141 142 } 143 144 }else{ 145 displayRequestErrors(recoverResultType); 146 } 147 148 } catch (Exception e) { 149 throw new ErrorAdminCommandException(e); 150 } 151 } 152 153 private X509Certificate getCert(String filename, String certEncoding) { 154 X509Certificate retval = null; 155 156 if(certEncoding.equals(ENCODING_PEM)){ 157 try { 158 Collection certs = CertTools.getCertsFromPEM(filename); 159 if(certs.size() > 0){ 160 retval = (X509Certificate ) certs.iterator().next(); 161 } 162 } catch (Exception e) {} 163 164 } 165 if(certEncoding.equals(ENCODING_DER)){ 166 try { 167 byte[] certdata = loadCert(filename); 168 retval = CertTools.getCertfromByteArray(certdata); 169 } catch (CertificateException e) { 170 } 171 } 172 173 if(retval == null){ 174 getPrintStream().println("Error couldn't decode certificate " + filename); 175 usage(); 176 System.exit(-1); 177 } 178 179 return retval; 180 } 181 182 private String getCertEncoding(String arg) { 183 if(arg.equalsIgnoreCase(ENCODING_PEM)){ 184 return ENCODING_PEM; 185 } 186 187 if(arg.equalsIgnoreCase(ENCODING_DER)){ 188 return ENCODING_DER; 189 } 190 191 getPrintStream().println("Illegal cert encoding(should be pem, der) : " + arg); 192 usage(); 193 System.exit(-1); 194 return null; 195 } 196 197 private X509Certificate getUserCert(Collection certs) { 198 X509Certificate retval = null; 199 Iterator iter = certs.iterator(); 200 while(iter.hasNext()){ 201 X509Certificate next = (X509Certificate ) iter.next(); 202 if(next.getBasicConstraints() == -1){ 203 retval = next; 204 break; 205 } 206 } 207 208 return retval; 209 } 210 211 private void createKeyStore(X509Certificate userCert, List caCerts, PrivateKey privKey, String password, String encoding, String outputPath) throws Exception { 212 boolean createJKS = false; 213 boolean createPEM = false; 214 if(encoding.equals(ENCODING_JKS)){ 215 createJKS = true; 216 } 217 if(encoding.equals(ENCODING_PEM)){ 218 createPEM = true; 219 } 220 221 String alias = getAlias(userCert); 222 223 Certificate [] caChain = new Certificate [caCerts.size()]; 224 for(int i=0;i<caCerts.size();i++){ 225 caChain[i] = (Certificate ) caCerts.get(i); 226 } 227 228 KeyStore ks = null; 230 231 if (createJKS) { 232 ks = KeyTools.createJKS(alias, privKey, password, userCert, caChain); 233 } else { 234 ks = KeyTools.createP12(alias, privKey, userCert, caChain); 235 } 236 237 storeKeyStore(ks, alias, password, createJKS, createPEM, outputPath); 238 239 } 240 241 private String getAlias(X509Certificate userCert) { 242 String alias = CertTools.getPartFromDN(CertTools.getSubjectDN(userCert), "CN"); 243 if (alias == null) alias = "myKey"; 244 return alias; 245 } 246 247 private List getCertsFromKeyBinding(KeyBindingType keyBinding) throws CertificateException { 248 ArrayList retval = new ArrayList (); 249 250 JAXBElement<X509DataType> jAXBX509Data = (JAXBElement<X509DataType>) keyBinding.getKeyInfo().getContent().get(0); 251 Iterator iter2 = jAXBX509Data.getValue().getX509IssuerSerialOrX509SKIOrX509SubjectName().iterator(); 252 while(iter2.hasNext()){ 253 JAXBElement next = (JAXBElement) iter2.next(); 254 if(next.getName().getLocalPart().equals("X509Certificate")){ 255 byte[] encoded = (byte[]) next.getValue(); 256 X509Certificate nextCert = CertTools.getCertfromByteArray(encoded); 257 retval.add(nextCert); 258 } 259 } 260 261 return retval; 262 } 263 264 private void displayRequestErrors(RecoverResultType recoverResultType) { 265 if(recoverResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_NOMATCH)){ 266 getPrintStream().println("Error no user with given certificate could be found"); 267 }else 268 if(recoverResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_NOAUTHENTICATION)){ 269 getPrintStream().println("Error password couldn't be verified"); 270 }else 271 if(recoverResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_REFUSED)){ 272 getPrintStream().println("The user doesn't seem to have the wrong status."); 273 }else{ 274 getPrintStream().println("Error occured during processing : " + recoverResultType.getResultMinor()); 275 } 276 } 277 278 279 283 private String useEncoding(String arg){ 284 if(arg.equalsIgnoreCase(ENCODING_PEM)){ 285 return ENCODING_PEM; 286 } 287 288 if(arg.equalsIgnoreCase(ENCODING_P12)){ 289 return ENCODING_P12; 290 } 291 292 if(arg.equalsIgnoreCase(ENCODING_JKS)){ 293 return ENCODING_JKS; 294 } 295 296 getPrintStream().println("Illegal encoding (should be pem, p12 or jks) : " + arg); 297 usage(); 298 System.exit(-1); 299 return null; 300 } 301 302 303 304 protected void usage() { 305 getPrintStream().println("Command used to recover the private key of a certificate"); 306 getPrintStream().println("Usage : recover <cert file name> <cert encoding (der|pem)> <password> <keystore encoding pem|p12|jks> <outputpath (optional)> \n\n"); 307 getPrintStream().println("Certificate encoding of the certificate about to recover key for, PEM and DER supported.\n"); 308 getPrintStream().println("Password used to authenticate to the XKMS service.\n"); 309 getPrintStream().println("Use pem, p12 or jks for encoding of the generated keystore.\n"); 310 getPrintStream().println("Outputpath specifies to which directory to write the keystore to, current directory is used if omitted\n\n"); 311 getPrintStream().println("Example: recover lostcert.pem pem \"foo123\" pem"); 312 getPrintStream().println("Recovers the key to the lostcert.pem certificate and writes it in PEM encoding in the current directory"); 313 314 315 } 316 317 318 } 319 | Popular Tags |