¿Cómo importar una clave pública simple al almacén de claves de Java?

0

Quiero importar una clave pública única (.pem) a un almacén de claves Java (.jks). No tengo la clave privada. Según tengo entendido, la clave pública debe incluirse como un certificado, de modo que pueda importarla en un almacén de claves de Java.

El contenido .pem se ve como:

-----BEGIN PUBLIC KEY-----
key_content....
-----END PUBLIC KEY-----

¿Existe la posibilidad de convertir una clave pública simple a un certificado, de modo que pueda importarla en un almacén de claves de Java? ¿O hay alguna otra opción para importar una clave pública en un almacén de claves de Java?

Simplemente convertir la clave pública de .pem a .der no es suficiente. La clave pública se utiliza para el cifrado programático de datos, no para TLS.

    
pregunta trunkc 10.02.2018 - 10:56
fuente

2 respuestas

3

El proceso de solicitud de certificado estándar (o al menos convencional) requiere que se certifique la clave privada que coincide con la publicación. Las operaciones preempaquetadas de la utilidad keytool de Java y la línea de comando openssl están limitadas a este proceso estándar, al igual que varias otras Qs existentes.

Sin embargo, no es fundamentalmente necesario. Siempre que tenga una clave privada para el certificado emisor , nominalmente una Autoridad de Certificación y un certificado para esa clave de CA o al menos algunos metadatos críticos normalmente incluidos en dicho certificado, es posible emitir una certificado de niño para un niño dado publickey.

Esto se puede hacer con OpenSSL llamando a las rutinas X509_* en libcrypto desde un código personalizado; en Java, las clases utilizadas por el estándar keytool no son oficialmente parte de la especificación JRE, pero son de código abierto, pero si puede usar las bibliotecas de terceros BouncyCastle (bcprov + bcpkix), exponen directamente las funciones necesarias de forma conveniente y documentada. / Forma garantizada, asi que lo demuestro. Esto crea un certificado muy mínimo con poca información y, especialmente, ninguna de las extensiones que están comúnmente presentes en los certificados reales, emitidos por CA. Si esto no es suficiente para sus necesidades, haga una pregunta más completa.

Por simplicidad leí el PEM de pubkey (sujeto) de un archivo con nombre, y la clave de CA y el certificado de un JKS en un archivo con nombre en un alias con nombre. Estas fuentes de información pueden ser reemplazadas por otras a su gusto. Tampoco hago ningún manejo de errores dejando que Java haga su seguimiento de pila predeterminado; Es posible que necesites algo mejor.

import java.security.*;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

static void Se179526FakeCert (String[] args) throws Exception {
    // pubkey.pem cakey.jks pw alias 
    Object spki  = new PEMParser (new FileReader (args[0])).readObject();
    KeyStore ks = KeyStore.getInstance("JKS"); 
    ks.load (new FileInputStream (args[1]), args[2].toCharArray());
    PrivateKey cakey = (PrivateKey) ks.getKey (args[3], args[2].toCharArray());
    X509Certificate cacert = (X509Certificate) ks.getCertificate (args[3]);
    Date now = new Date(), exp = new Date(now.getTime()+30*86400*1000); // 30 days validity

    ContentSigner signer = new JcaContentSignerBuilder ("SHA256with"+cakey.getAlgorithm()).build(cakey);
    byte[] enc = new X509v3CertificateBuilder(
            /*issuer*/new X500Name (cacert.getIssuerX500Principal().getName()), /*serial*/BigInteger.valueOf(now.getTime()),
            /*validity*/now, exp, /*subject*/new X500Name ("CN=dummy"), /*spki*/(SubjectPublicKeyInfo) spki 
        ) .build(signer) .getEncoded();
    // .addExtension's if&as needed before .build
    Certificate cert = CertificateFactory.getInstance ("X.509") .generateCertificate(new ByteArrayInputStream(enc));
    // could now store in a keystore; or to write out in PEM:
    JcaPEMWriter out = new JcaPEMWriter (new OutputStreamWriter (System.out));
    out.writeObject (cert); out.flush(); 
}
    
respondido por el dave_thompson_085 12.02.2018 - 08:36
fuente
1

No, no puede generar un certificado válido sin proporcionar la clave privada. Si necesita un certificado, el titular de la clave privada debe solicitarlo.

De lo contrario, los certificados no tendrían sentido porque cualquier persona podría crear un certificado para cualquier dominio para cualquier clave pública de su elección.

    
respondido por el John Deters 10.02.2018 - 15:37
fuente

Lea otras preguntas en las etiquetas