1 13 14 package org.ejbca.core.protocol.xkms.client; 15 16 import java.security.KeyPair ; 17 import java.security.KeyStore ; 18 import java.security.PrivateKey ; 19 import java.security.cert.Certificate ; 20 import java.security.cert.CertificateException ; 21 import java.security.cert.X509Certificate ; 22 import java.security.interfaces.RSAPublicKey ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 import javax.xml.bind.JAXBElement; 29 30 import org.ejbca.core.protocol.xkms.common.XKMSConstants; 31 import org.ejbca.core.protocol.xkms.common.XKMSUtil; 32 import org.ejbca.ui.cli.ErrorAdminCommandException; 33 import org.ejbca.ui.cli.IAdminCommand; 34 import org.ejbca.ui.cli.IllegalAdminCommandException; 35 import org.ejbca.util.CertTools; 36 import org.ejbca.util.KeyTools; 37 import org.w3._2000._09.xmldsig_.KeyInfoType; 38 import org.w3._2000._09.xmldsig_.RSAKeyValueType; 39 import org.w3._2000._09.xmldsig_.X509DataType; 40 import org.w3._2002._03.xkms_.KeyBindingType; 41 import org.w3._2002._03.xkms_.ObjectFactory; 42 import org.w3._2002._03.xkms_.PrototypeKeyBindingType; 43 import org.w3._2002._03.xkms_.RegisterRequestType; 44 import org.w3._2002._03.xkms_.RegisterResultType; 45 import org.w3._2002._03.xkms_.UseKeyWithType; 46 47 48 49 50 51 57 public class RegisterCommand extends XKMSCLIBaseCommand implements IAdminCommand{ 58 59 private ObjectFactory xKMSObjectFactory = new ObjectFactory(); 60 private org.w3._2000._09.xmldsig_.ObjectFactory sigFactory = new org.w3._2000._09.xmldsig_.ObjectFactory(); 61 62 private static final int ARG_DN = 1; 63 private static final int ARG_PASSWORD = 2; 64 private static final int ARG_REVOCATIONCODEID = 3; 65 private static final int ARG_KEYSIZE = 4; 66 private static final int ARG_ENCODING = 5; 67 private static final int ARG_OUTPUTPATH = 6; 68 69 70 71 76 public RegisterCommand(String [] args) { 77 super(args); 78 } 79 80 86 public void execute() throws IllegalAdminCommandException, ErrorAdminCommandException { 87 88 try { 89 90 if(args.length < 6 || args.length > 7){ 91 usage(); 92 System.exit(-1); 93 } 94 95 String subjectDN = args[ARG_DN]; 96 String password = args[ARG_PASSWORD]; 97 98 String revocationCodeId = args[ARG_REVOCATIONCODEID]; 99 100 String encoding = useEncoding(args[ARG_ENCODING]); 101 102 int keySize = getKeySize(args[ARG_KEYSIZE]); 103 104 105 String outputPath = ""; 106 if(args.length >= ARG_OUTPUTPATH +1){ 107 if(args[ARG_OUTPUTPATH] != null){ 108 outputPath = args[ARG_OUTPUTPATH] + "/"; 109 } 110 } 111 112 KeyPair genKeys = null; 113 if(keySize != 0){ 114 genKeys = KeyTools.genKeys(Integer.toString(keySize), "RSA"); 115 } 116 117 String keyBindingId = genId(); 118 PrototypeKeyBindingType prototypeKeyBinding = xKMSObjectFactory.createPrototypeKeyBindingType(); 119 prototypeKeyBinding.setId(keyBindingId); 120 UseKeyWithType useKeyWithType = xKMSObjectFactory.createUseKeyWithType(); 121 useKeyWithType.setApplication(XKMSConstants.USEKEYWITH_PKIX); 122 useKeyWithType.setIdentifier(subjectDN); 123 prototypeKeyBinding.getUseKeyWith().add(useKeyWithType); 124 125 if(revocationCodeId != null && !revocationCodeId.equalsIgnoreCase("NULL")){ 126 byte[] first = XKMSUtil.getSecretKeyFromPassphrase(revocationCodeId, true,20, XKMSUtil.KEY_REVOCATIONCODEIDENTIFIER_PASS1).getEncoded(); 127 byte[] second = XKMSUtil.getSecretKeyFromPassphrase(new String (first,"ISO8859-1"), false,20, XKMSUtil.KEY_REVOCATIONCODEIDENTIFIER_PASS2).getEncoded(); 128 prototypeKeyBinding.setRevocationCodeIdentifier(second); 129 } 130 131 String reqId = genId(); 132 RegisterRequestType registerRequestType = xKMSObjectFactory.createRegisterRequestType(); 133 registerRequestType.setId(reqId); 134 registerRequestType.getRespondWith().add(XKMSConstants.RESPONDWITH_X509CHAIN); 135 if(keySize == 0){ 136 registerRequestType.getRespondWith().add(XKMSConstants.RESPONDWITH_PRIVATEKEY); 137 } 138 registerRequestType.setPrototypeKeyBinding(prototypeKeyBinding); 139 140 RegisterResultType registerResultType = null; 141 if(genKeys == null){ 142 registerResultType = getXKMSInvoker().register(registerRequestType, clientCert, privateKey, password, null, keyBindingId); 143 }else{ 144 KeyInfoType keyInfoType = sigFactory.createKeyInfoType(); 145 RSAKeyValueType rsaKeyValueType = sigFactory.createRSAKeyValueType(); 146 rsaKeyValueType.setExponent(((RSAPublicKey ) genKeys.getPublic()).getPublicExponent().toByteArray()); 147 rsaKeyValueType.setModulus(((RSAPublicKey ) genKeys.getPublic()).getModulus().toByteArray()); 148 JAXBElement<RSAKeyValueType> rsaKeyValue = sigFactory.createRSAKeyValue(rsaKeyValueType); 149 keyInfoType.getContent().add(rsaKeyValue); 150 151 prototypeKeyBinding.setKeyInfo(keyInfoType); 152 153 registerResultType = getXKMSInvoker().register(registerRequestType, clientCert, privateKey, password, genKeys.getPrivate(), keyBindingId); 154 } 155 156 if(registerResultType.getResultMajor().equals(XKMSConstants.RESULTMAJOR_SUCCESS) && 157 registerResultType.getResultMinor() == null){ 158 159 if(registerResultType.getKeyBinding().size() >0){ 160 KeyBindingType keyBinding = registerResultType.getKeyBinding().get(0); 161 List certs = getCertsFromKeyBinding(keyBinding); 162 163 X509Certificate userCert = getUserCert(certs); 164 certs.remove(userCert); 165 166 if(registerResultType.getPrivateKey() != null){ 167 PrivateKey serverKey = XKMSUtil.getPrivateKeyFromEncryptedXML(registerResultType.getPrivateKey(), password); 168 createKeyStore(userCert, certs, serverKey,password,encoding,outputPath); 169 }else{ 170 createKeyStore(userCert, certs,genKeys.getPrivate(),password,encoding,outputPath); 171 } 172 173 } 174 175 }else{ 176 displayRequestErrors(registerResultType); 177 } 178 179 } catch (Exception e) { 180 throw new ErrorAdminCommandException(e); 181 } 182 } 183 184 private X509Certificate getUserCert(Collection certs) { 185 X509Certificate retval = null; 186 Iterator iter = certs.iterator(); 187 while(iter.hasNext()){ 188 X509Certificate next = (X509Certificate ) iter.next(); 189 if(next.getBasicConstraints() == -1){ 190 retval = next; 191 break; 192 } 193 } 194 195 return retval; 196 } 197 198 private void createKeyStore(X509Certificate userCert, List caCerts, PrivateKey privKey, String password, String encoding, String outputPath) throws Exception { 199 boolean createJKS = false; 200 boolean createPEM = false; 201 if(encoding.equals(ENCODING_JKS)){ 202 createJKS = true; 203 } 204 if(encoding.equals(ENCODING_PEM)){ 205 createPEM = true; 206 } 207 208 String alias = getAlias(userCert); 209 210 Certificate [] caChain = new Certificate [caCerts.size()]; 211 for(int i=0;i<caCerts.size();i++){ 212 caChain[i] = (Certificate ) caCerts.get(i); 213 } 214 215 KeyStore ks = null; 217 218 if (createJKS) { 219 ks = KeyTools.createJKS(alias, privKey, password, userCert, caChain); 220 } else { 221 ks = KeyTools.createP12(alias, privKey, userCert, caChain); 222 } 223 224 storeKeyStore(ks, alias, password, createJKS, createPEM, outputPath); 225 226 } 227 228 private String getAlias(X509Certificate userCert) { 229 String alias = CertTools.getPartFromDN(CertTools.getSubjectDN(userCert), "CN"); 230 if (alias == null) alias = "myKey"; 231 return alias; 232 } 233 234 private List getCertsFromKeyBinding(KeyBindingType keyBinding) throws CertificateException { 235 ArrayList retval = new ArrayList (); 236 237 JAXBElement<X509DataType> jAXBX509Data = (JAXBElement<X509DataType>) keyBinding.getKeyInfo().getContent().get(0); 238 Iterator iter2 = jAXBX509Data.getValue().getX509IssuerSerialOrX509SKIOrX509SubjectName().iterator(); 239 while(iter2.hasNext()){ 240 JAXBElement next = (JAXBElement) iter2.next(); 241 if(next.getName().getLocalPart().equals("X509Certificate")){ 242 byte[] encoded = (byte[]) next.getValue(); 243 X509Certificate nextCert = CertTools.getCertfromByteArray(encoded); 244 retval.add(nextCert); 245 } 246 } 247 248 return retval; 249 } 250 251 private void displayRequestErrors(RegisterResultType registerResultType) { 252 if(registerResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_NOMATCH)){ 253 getPrintStream().println("Error no user with given subjectDN could be found"); 254 }else 255 if(registerResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_NOAUTHENTICATION)){ 256 getPrintStream().println("Error password couldn't be verified"); 257 }else 258 if(registerResultType.getResultMinor().equals(XKMSConstants.RESULTMINOR_REFUSED)){ 259 getPrintStream().println("The user doesn't seem to have the wrong status."); 260 }else{ 261 getPrintStream().println("Error occured during processing : " + registerResultType.getResultMinor()); 262 } 263 } 264 265 private int getKeySize(String keySize) { 266 int retval =0; 267 try{ 268 if(!keySize.equalsIgnoreCase("NOGEN")){ 269 retval = Integer.parseInt(keySize); 270 271 if(retval != 512 && retval != 1024 && retval != 2048 && retval != 4096){ 272 getPrintStream().println("Illegal keysize : should be a number of 512, 1024, 2048, 4096 or 'NOGEN': " + keySize); 273 usage(); 274 System.exit(-1); 275 } 276 } 277 278 279 }catch(NumberFormatException e){ 280 getPrintStream().println("Illegal keysize : should be a number or 'NOGEN': " + keySize); 281 usage(); 282 System.exit(-1); 283 } 284 return retval; 285 } 286 287 288 292 private String useEncoding(String arg){ 293 if(arg.equalsIgnoreCase(ENCODING_PEM)){ 294 return ENCODING_PEM; 295 } 296 297 if(arg.equalsIgnoreCase(ENCODING_P12)){ 298 return ENCODING_P12; 299 } 300 301 if(arg.equalsIgnoreCase(ENCODING_JKS)){ 302 return ENCODING_JKS; 303 } 304 305 getPrintStream().println("Illegal encoding (should be pem, p12 or jks) : " + arg); 306 usage(); 307 System.exit(-1); 308 return null; 309 } 310 311 312 313 protected void usage() { 314 getPrintStream().println("Command used to register for a certificate"); 315 getPrintStream().println("Usage : register <subjectDN> <password> <revocationCodeIdentifier> <keySize> <pem|p12|jks> <outputpath (optional)> \n\n"); 316 getPrintStream().println("The revocationCodeIdentifier is a passphrase or 'NULL' if it isn't used.\n"); 317 getPrintStream().println("keySize of the generated RSA keys, are only used for client generated keys, use 'NOGEN' othervise.\n"); 318 getPrintStream().println("Use pem, p12 or jks for encoding of the generated keystore.\n"); 319 getPrintStream().println("Outputpath specifies to which directory to write the keystore to, current directory is used if omitted\n\n"); 320 getPrintStream().println("Example: register \"CN=Test Testarson,O=someorg\" \"foo123\" \"My passphrase\" 2048 pem"); 321 getPrintStream().println("Issues a certificate to to \"CN=Test Testarson,O=someorg\" and writes it in PEM encoding in the current directory"); 322 323 324 } 325 326 327 } 328 | Popular Tags |