Come importare una chiave pubblica semplice nel keystore java?

0

Voglio importare una chiave pubblica solitaria (.pem) in un keystore Java (.jks). Non ho la chiave privata. Come ho capito, la chiave pubblica deve essere impacchettata come certificato, in modo da poterla importare in un keystore java.

Il contenuto di .pem è:

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

Esiste la possibilità di convertire una chiave pubblica semplice in un certificato, in modo da poterla importare in un keystore java? O c'è qualche altra opzione per importare una chiave pubblica in un keystore java?

La semplice conversione della chiave pubblica da .pem a .der non è sufficiente. La chiave pubblica viene utilizzata per la crittografia programmatica dei dati, non per TLS.

    
posta trunkc 10.02.2018 - 10:56
fonte

2 risposte

3

Il processo di richiesta del certificato standard (o almeno convenzionale) richiede che la chiave privata corrisponda al publickey per essere certificato. Le operazioni preconfezionate dell'utilità keytool di Java e della riga di comando openssl sono limitate a questo processo standard, come lo sono molte altre Q esistenti.

Tuttavia, non è fondamentalmente necessario. Finché si ha una chiave privata per il certificato emittente , nominalmente un'autorità di certificazione e un certificato per quella chiave CA o almeno alcuni metadati critici normalmente incorporati in tale certificato, è possibile emettere un certificato di bambino per un determinato bambino publickey.

Questo può essere fatto con OpenSSL chiamando le routine X509_* in libcrypto dal codice personalizzato; in Java le classi usate dallo standard keytool non sono ufficialmente parte delle specifiche JRE ma sono open source, ma se puoi usare le librerie di terze parti BouncyCastle (bcprov + bcpkix) espongono direttamente le funzioni necessarie in un modo conveniente e documentato / forma garantita, quindi lo mostro. Questo crea un certificato molto minimale con poche informazioni e in particolare nessuna delle estensioni comunemente presenti nei certificati reali emessi dalla CA. Se questo non è sufficiente per le tue esigenze, fai una domanda più completa.

Per semplicità leggo il PEM pubkey (soggetto) da un file con nome e la chiave CA e cert da un JKS in un file con nome in un alias denominato. Queste fonti di informazione possono essere sostituite da altre come desideri. Inoltre, non eseguo alcuna gestione degli errori, lasciando Java a fare lo stacktrace predefinito; potresti aver bisogno di meglio.

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(); 
}
    
risposta data 12.02.2018 - 08:36
fonte
1

No, non è possibile generare un certificato valido senza fornire la chiave privata. Se hai bisogno di un certificato, il titolare della chiave privata deve richiederlo.

Altrimenti, i certificati sarebbero privi di significato perché chiunque potrebbe creare un certificato per qualsiasi dominio per qualsiasi chiave pubblica di loro scelta.

    
risposta data 10.02.2018 - 15:37
fonte

Leggi altre domande sui tag