2012-09-08 22 views
6

La pregunta es cómo generar cadenas de certificados mediante programación en Java. En otras palabras, me gustaría llevar a cabo en Java las operaciones detalladas aquí: http://fusesource.com/docs/broker/5.3/security/i382664.htmlGenerar cadena de certificados en java

Besically, que puede crear las claves RSA para un nuevo cliente:

private KeyPair genRSAKeyPair(){ 
    // Get RSA key factory: 
    KeyPairGenerator kpg = null; 
    try { 
     kpg = KeyPairGenerator.getInstance("RSA"); 
    } catch (NoSuchAlgorithmException e) { 
     log.error(e.getMessage()); 
     e.printStackTrace(); 
     return null; 
    } 
    // Generate RSA public/private key pair: 
    kpg.initialize(RSA_KEY_LEN); 
    KeyPair kp = kpg.genKeyPair(); 
    return kp; 

}

y generar el certificado correspondiente:

private X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm) 
    throws GeneralSecurityException, IOException { 
    PrivateKey privkey = pair.getPrivate(); 
    X509CertInfo info = new X509CertInfo(); 
    Date from = new Date(); 
    Date to = new Date(from.getTime() + days * 86400000l); 
    CertificateValidity interval = new CertificateValidity(from, to); 
    BigInteger sn = new BigInteger(64, new SecureRandom()); 
    X500Name owner = new X500Name(dn); 

    info.set(X509CertInfo.VALIDITY, interval); 
    info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn)); 
    info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner)); 
    info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner)); 
    info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic())); 
    info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); 
    AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid); 
    info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo)); 

    // Sign the cert to identify the algorithm that's used. 
    X509CertImpl cert = new X509CertImpl(info); 
    cert.sign(privkey, algorithm); 

    // Update the algorith, and resign. 
    algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG); 
    info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo); 
    cert = new X509CertImpl(info); 
    cert.sign(privkey, algorithm); 
    return cert; 

}

Entonces generar la solicitud de certificado de firma y guardarla en un archivo csrFile:

public static void writeCertReq(File csrFile, String alias, String keyPass, KeyStore ks) 
     throws KeyStoreException, 
       NoSuchAlgorithmException, 
       InvalidKeyException, 
       IOException, 
       CertificateException, 
       SignatureException, 
       UnrecoverableKeyException { 

    Object objs[] = getPrivateKey(ks, alias, keyPass.toCharArray()); 
    PrivateKey privKey = (PrivateKey) objs[0]; 

    PKCS10 request = null; 

    Certificate cert = ks.getCertificate(alias); 
    request = new PKCS10(cert.getPublicKey()); 
    String sigAlgName = "MD5WithRSA"; 
    Signature signature = Signature.getInstance(sigAlgName); 
    signature.initSign(privKey); 
    X500Name subject = new X500Name(((X509Certificate) cert).getSubjectDN().toString()); 
    X500Signer signer = new X500Signer(signature, subject); 
    request.encodeAndSign(signer); 
    request.print(System.out); 
    FileOutputStream fos = new FileOutputStream(csrFile); 
    PrintStream ps = new PrintStream(fos); 
    request.print(ps); 
    fos.close(); 
} 

donde

private static Object[] getPrivateKey(KeyStore ks, String alias, char keyPass[]) 
     throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException { 
    key = null;   
    key = ks.getKey(alias, keyPass); 
    return (new Object[]{ (PrivateKey) key, keyPass }); 
} 

Ahora debería firmar la RSE con la clave privada de la CA, pero no puedo ver cómo achive eso en java. Tengo mi propia clave privada de CA en mi jks.

Además, una vez que logro firmar el CSR, debo encadenar el certificado CA con el CSR firmado: ¿cómo se puede hacer eso en Java?

Preferiría no utilizar bc u otras libretas externas, solo las clases "sun.security".

Gracias.

Respuesta

2

Lo siento, pero a pesar de sus deseos, y además de escribir todo su código criptográfico y de incluirlo en su proyecto (no recomendado), recomendaría utilizar Bouncy Castle aquí.

Específicamente, consulte https://stackoverflow.com/a/7366757/751158 - que incluye el código para exactamente lo que usted está buscando hacer.

+0

Ok. Que así sea. Incorporaré BC y me beneficiaré de tu enlace. Gracias –

1

Veo que ya ha pasado al lado del BouncyCastle de la casa, pero por si acaso alguien más se preguntaba; puede agregar la cadena de cert a la entrada al poner la clave en KeyStore. Por ejemplo

// build your certs 

KeyStore keyStore = KeyStore.getInstance("PKCS12"); 
keyStore.load([keystore stream], password.toCharArray());// or null, null if it's a brand new store 
X509Certificate[] chain = new X509Certificate[2]; 
chain[0] = _clientCert; 
chain[1] = _caCert; 
keyStore.setKeyEntry("Alias", _clientCertKey, password.toCharArray(), chain); 
keyStore.store([output stream], password.toCharArray()); 

// do other stuff 
Cuestiones relacionadas