0

I have code that loads client private key

// load client private key
PEMParser pemParser = new PEMParser(new FileReader(keyFile));
Object object = pemParser.readObject();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");

KeyPair key;
if (object instanceof PEMEncryptedKeyPair) {
    System.out.println("Encrypted key - we will use provided password");
    key = converter.getKeyPair(((PEMEncryptedKeyPair) object)
            .decryptKeyPair(decProv));
} else {
    System.out.println("Unencrypted key - no password needed "+object.getClass().getName());
    key = converter.getKeyPair((PEMKeyPair) object);
}
pemParser.close();

In some cases pemParser.readObject() returns object of class PEMKeyPair and that is fine. But in case I have client key defined below pemParser.readObject() returns instance of PrivateKeyInfo. Why I'm getting PrivateKeyInfo and how to deal in such case?

client key :

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4weh0zOpMwqZc
y3oExJQ84Vhyrf/6IdGmUpHaexyrhbbuZD8SThb1O/pp/gs7ZOgqXLQx5jYEwncO
7VVlDJg8inKDaeDZn/EHmTqs4AVYAxvqXU4C9J3QKw4+zf/WRbvd1FWMvD/Lurqn
3/UF0iIjiyu/sZojyQ1VnWAHGtnuYIGEKij12fQt+AMhcuYKPExaCdB7rQocEnxw
/AxKRTHmRPHu9f1ny78ALCBMp8/3UdclHCL2Hszcpj+mfRwoRMVDER0LA3edUnGj
kkhbxGckSvGatmknNRzsf4XhSAfxb1kXEtX1ZQd7/ZPIxE1JZSbljgOIi5X1CLpc
gGD4vYaDAgMBAAECggEBALfa9vksZchnN2hGcDFIcf+3e+37Kyz99IQfzNbvBlPF
p4nJpl4P6Za2zfYmAYVkYAiv4f16Cq1n21S2ZvE8vE4as+QEO+Y03IVkPViFQawY
w/HQUe5tAJKEFhP3qSzQjigswclgF9gkBNVD76+QMbrPJoUHNs1/qE5XYpUPamlk
XFvw+7+DQVQpd4zMx0lP1zU9wdG4hX3639H+5SYHHDpfnjNk8vdVVmBZO0iPUjAO
gNs/yllqTRmqst7Nt4oVKb+Ygabv+j+nz55Z2kHNJGKQA4JoHXYcctNz9CjKOs0p
kHMsYQWnlPXYs/wrkUv+PnRP0Crwav/bjtDsDYLeeRECgYEA5eCEauTI4V0MU9dO
PV8sShNIfTBo9kjjrkUq3LTlUEk1nvBLtc1uyMQPRisTWYrG+InhRgyZvhax4wgK
ynuicxyB/5vyTA7OZl/kG2ikSllsDJrfAtFjqGDvuDKrNpo1u9dkrtvcZNdV5B4Z
ui4Ekh1v9iuciwma3nQita1v8IsCgYEAzcDKt3NTgsL/ilHO4bIIkXwf3Qltsnlf
hxVdfkaCWU653e7IVrLkORK2qCeDQDqh/H+58astuW6kw+WjcYuMY/4IXETsBhUv
zAKyuwSAXYva+Qpk7NIsgRBCYJbt6s6Q9Xnh2VKVHpWrWWZL05MmSbH/OHbjzPj2
KhVMytStyOkCgYEAmQorPjsIXbkjzuGFbihhhQNnfCjxiB2orsnPqlYoYJYMw764
uNWGztRwUse0vyU8KBUrTAZxiHL1hO9Ct+EtmrM8/N5mpiopUVC/vVuiHPmBjLbC
h869KUk37wqUn+p0oZTZq+wlw2D1BsTfXerrEhfVBS+trYb8euMYhJlt79cCgYBI
vF7te1eKYmT0APeh0c41oCujeDHPZhjfKC5k9YgfCjWqvz8TZypHAtaPm2hKzG93
U6/oPxtq8jJNDmE5QpvevW83LyZBADxlYo7MjkrSxx4h7ArBrYsOFTFh8/kniN61
6OBuc0NEDKUGdaNYqCxg4QvYai8dxuU++0iqa4UEAQKBgB01N4lwaUDf2NAagr4j
c9ctHWdK8Zmic8YDGpTu2EFDaFuBOpcy9dmdrluikQOtX1zBcp0pxQCVBHzT/3bE
DBRxQocxhzKzUZlxxnHsbXTJlXvatxlkkU5zxsmj1zX3p/we46F7nkP7n7jabH+V
sNRd5qP8b/Dm0tXxUAZ1uOb6
-----END PRIVATE KEY-----

UPD

To be honest I'm not strong in security and I have no idea how to construct KeyStore object when I'm getting PrivateKeyInfo from pemParser.readObject().

Full program code:

public class TestMQTT2 {

    public static void main(String[] args) {

        //bandom open source 
        //https://github.com/hivemq/mqtt-cli

        //String serverUrl = "ssl://192.168.1.8:8885";
        String serverUrl = "ssl://192.168.1.8:8884";

        //String path= "C:\\projects\\certs\\cert10\\";
        String path= "C:\\projects\\certs\\cert8\\";
        String caFilePath =path+"ca.crt";
        String clientCrtFilePath = path+ "client.crt";
        String clientKeyFilePath = path+ "client.key";
        String mqttUserName = "b";
        String mqttPassword = "b";

        MqttClient client;
        try {
            client = new MqttClient(serverUrl, "2");
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(mqttUserName);
            options.setPassword(mqttPassword.toCharArray());

            options.setConnectionTimeout(60);
            options.setKeepAliveInterval(60);
            options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);


            SSLSocketFactory socketFactory = getSocketFactory(caFilePath,clientCrtFilePath, clientKeyFilePath, "vlk32gm5");
            options.setSocketFactory(socketFactory);

            System.out.println("starting connect the server...");
            client.connect(options);
            System.out.println("connected!");
            Thread.sleep(1000);

            client.subscribe(
                    "/u/56ca327d17531d08e76bddd4a215e37f5fd6082f7442151c4d3f1d100a0ffd4e",
                    0);
            client.disconnect();
            System.out.println("disconnected!");


        } catch (MqttException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static SSLSocketFactory getSocketFactory(final String caCrtFile,
            final String crtFile, final String keyFile, final String password)
            throws Exception {
        Security.addProvider(new BouncyCastleProvider());

        // load CA certificate
        X509Certificate caCert = null;

        FileInputStream fis = new FileInputStream(caCrtFile);
        BufferedInputStream bis = new BufferedInputStream(fis);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        while (bis.available() > 0) {
            caCert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }

        // load client certificate
        bis = new BufferedInputStream(new FileInputStream(crtFile));
        X509Certificate cert = null;
        while (bis.available() > 0) {
            cert = (X509Certificate) cf.generateCertificate(bis);
            // System.out.println(caCert.toString());
        }

        // load client private key
        PEMParser pemParser = new PEMParser(new FileReader(keyFile));
        Object object = pemParser.readObject();
        PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");

        KeyPair key;
        if (object instanceof PEMEncryptedKeyPair) {
            System.out.println("Encrypted key - we will use provided password");
            key = converter.getKeyPair(((PEMEncryptedKeyPair) object)
                    .decryptKeyPair(decProv));
        } else {
            System.out.println("Unencrypted key - no password needed "+object.getClass().getName());

            key = converter.getKeyPair((PEMKeyPair) object);
        }
        pemParser.close();

        // CA certificate is used to authenticate server
        KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
        caKs.load(null, null);
        caKs.setCertificateEntry("ca-certificate", caCert);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(caKs);

        // client key and certificates are sent to server so it can authenticate
        // us
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        ks.setCertificateEntry("certificate", cert);
        ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
                new java.security.cert.Certificate[] { cert });
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
                .getDefaultAlgorithm());
        kmf.init(ks, password.toCharArray());

        // finally, create SSL socket factory
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }


}
vico
  • 17,051
  • 45
  • 159
  • 315
  • The [javadocs](https://www.bouncycastle.org/docs/pkixdocs1.5on/org/bouncycastle/openssl/PEMParser.html) explain when you get a `PrivateKeyInfo` or a `PEMKeyPair` object. What is the problem you have when dealing with such a case? – Progman Jan 09 '20 at 19:23
  • To be honest I'm not strong in security and I have no idea how to construct `KeyStore` object when I'm getting `PrivateKeyInfo` from pemParser.readObject(). More details in UPD. – vico Jan 09 '20 at 21:10
  • To create a KeyStore from a PEM file, See https://stackoverflow.com/questions/2138940/import-pem-into-java-key-store/48173910#48173910 – BluEOS Jan 09 '20 at 21:39
  • Just to be clear, you have now revealed that private key to the world, and all future and past data secured or signed with it is now vulnerable, at least signatures that are not securely timestamped before you posted it. So I hope this is just a test key. – President James K. Polk Jan 12 '20 at 20:52
  • What have an unencrypted PKCS8 private key. There is not much reason to use Bouncycastle to parse these. Just remove the header and trailer lines, and all the whitespace, and base64-decode what's left. That `byte[]` should be used in the constructor for [`PKCS8EncodedKeySpec`](https://docs.oracle.com/javase/8/docs/api/java/security/spec/PKCS8EncodedKeySpec.html#PKCS8EncodedKeySpec-byte:A-). Then you can get the private key with `KeyFactory.getInstance("RSA").generatePrivate(...)` and store it in a keystore. – President James K. Polk Jan 12 '20 at 20:57

0 Answers0