2011-09-27 6 views
5

Estoy tratando de generar certificados X509 con bouncycastle 1.46, con el siguiente código. El problema que tengo es que cuando un certificado se escribe en un JKS y luego se vuelve a leer, los DN se invierten. Por ejemplo, si se me acaba el código de abajo, me sale el siguiente resultado:Atributos invertidos en el tema del certificado y el emisor

CN=test,O=gina 
CN=test,O=gina 
CN=test,O=gina 
O=gina, CN=test 

¿Alguien sabe la razón de esto? cómo evitarlo? Gracias de antemano.

Código:

public static void main(String[] args) { 
    try { 
     Security.addProvider(new BouncyCastleProvider()); 

     KeyPair pair = generateKeyPair("RSA", 1024); 
     X500Name principal = new X500Name("cn=test,o=gina"); 
     System.out.println(principal); 
     BigInteger sn = BigInteger.valueOf(1234); 
     Date start = today(); 
     Date end = addYears(start, 2); 
     X509Certificate cert = generateCert(principal, pair, sn, start, end, 
       "SHA1withRSA"); 
     cert.verify(pair.getPublic()); 
     System.out.println(cert.getSubjectDN()); 

     // Store the certificate in the JKS 
     KeyStore ks = KeyStore.getInstance("JKS"); 
     ks.load(null, null); 
     ks.setKeyEntry("alias", pair.getPrivate(), KEY_PWD, 
       new X509Certificate[] {cert}); 
     X509Certificate c 
       = (X509Certificate)ks.getCertificateChain("alias")[0]; 
     System.out.println(c.getSubjectDN()); 
     OutputStream out = new FileOutputStream("text.jks"); 
     try { 
      ks.store(out, KEYSTORE_PWD); 
     } finally { 
      out.close(); 
     } 

     // Reread the JKS 
     ks = KeyStore.getInstance("JKS"); 
     InputStream in = new FileInputStream("text.jks"); 
     try { 
      ks.load(in, KEYSTORE_PWD); 
     } finally { 
      in.close(); 
     } 
     c = (X509Certificate)ks.getCertificateChain("alias")[0]; 
     c.verify(pair.getPublic()); 
     System.out.println(c.getSubjectDN()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

private static X509Certificate generateCert(X500Name principal, 
     KeyPair pair, BigInteger sn, Date start, Date end, String sigalg) 
     throws OperatorCreationException, CertificateException { 
    JcaX509v3CertificateBuilder certGen 
      = new JcaX509v3CertificateBuilder(principal, sn, start, end, 
        principal, pair.getPublic()); 
    JcaContentSignerBuilder builder 
      = new JcaContentSignerBuilder(sigalg); 
    builder.setProvider("BC"); 
    ContentSigner signr = builder.build(pair.getPrivate()); 
    X509CertificateHolder certHolder = certGen.build(signr); 
    JcaX509CertificateConverter conv 
      = new JcaX509CertificateConverter(); 
    conv.setProvider("BC"); 
    return conv.getCertificate(certHolder); 
} 

private static KeyPair generateKeyPair(String algorithm, int keySize) 
     throws NoSuchAlgorithmException { 
    KeyPairGenerator gen = KeyPairGenerator.getInstance(algorithm); 
    gen.initialize(keySize); 
    return gen.generateKeyPair(); 
} 

private static Date today() { 
    Calendar cal = Calendar.getInstance(); 
    cal.set(Calendar.HOUR_OF_DAY, 0); 
    cal.set(Calendar.MINUTE, 0); 
    cal.set(Calendar.SECOND, 0); 
    cal.set(Calendar.MILLISECOND, 0); 
    return cal.getTime(); 
} 

private static Date addYears(Date date, int count) { 
    Calendar cal = Calendar.getInstance(); 
    cal.setTime(date); 
    cal.add(Calendar.YEAR, count); 
    return cal.getTime(); 
} 

Respuesta

5

me encontré con el mismo problema y resuelto rápidamente con lo siguiente:

//CREATES AN X500 CA SUBJECT FOR ISSUER 

X500Name issuerName = new JcaX509CertificateHolder((X509Certificate) caCert).getSubject(); 

que entonces se utiliza con lo siguiente:

//CONSTRUCTS THE X509 CERTIFIFATE OBJECT 

X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(
issuerName, 
serialNumber, 
startDate, endDate, 
DevCsr.getSubject(), 
DevCsr.getSubjectPublicKeyInfo()); 

el nombre del emisor en el certificado de entidad final almacén de claves Java muestra ahora en el orden correcto

¡Salud!

3

tuve el mismo problema con saltos de 1.47.

Primero debe tener cuidado con las clases X500Name y X500Principal. Están las clases SUN y las clases hinchables. ¡Son totalmente diferentes!

X500Name (hinchable) debe crearse utilizando X500NameBuilder. Pero si necesita crearlo usando un String, sus atributos deben estar en el orden inverso al RFC2253, esto significa que sus atributos deben estar en este orden: "CN, L, ST, O, OU, C, STREET, DC, UID ".

Esto no es conveniente porque, por ejemplo, en mi caso, tuve que crear un X500Name (hinchable) desde un X500Principal (SUN) y la única manera de hacerlo era usar el método X500Principal: getName() que imprima los atributos de acuerdo con el orden RFC2253. Así que creé este método:

private org.bouncycastle.asn1.x500.X500Name toBouncyX500Name(javax.security.auth.x500.X500Principal principal) { 

    String name = principal.getName(); 

    String[] RDN = name.split(","); 

    StringBuffer buf = new StringBuffer(name.length()); 
    for(int i = RDN.length - 1; i >= 0; i--){ 
     if(i != RDN.length - 1) 
      buf.append(','); 

     buf.append(RDN[i]); 
    } 

    return new X500Name(buf.toString()); 
} 

espero que sea útil a alguien :)

5

Esto puede ser un poco más simple. Al menos en BC 1.48+, se puede construir el X500Name thusly, y los OID se ordenarán de la forma esperada (o al menos, de la forma que se especifica):

final X500Name subject = new X500Name(RFC4519Style.INSTANCE, "CN=test,O=gina"); 
+0

creo que debería ser la respuesta – mlapeyre

Cuestiones relacionadas