4
votes

I want to convert pem file to pk8. I can do this with openssl on terminal as ;

openssl pkcs8 -topk8 -inform PEM -outform DER -in client-key.pem -out client-key.pk8 -nocrypt

But I need to do this programmatically on java. Its look like there is a package for cryptography which contains openssl implementation as Bounty Castle but I couldn't figure out how can do this converting process. Is there a way for doing that ?

1
Could you provide more detail about the type of key you have in PEM encoding and how it is formatted? If you do not know, could you give the output of cat client-key.pem | head -n 1 or copy the first line of the client-key.pem file?Reinier Torenbeek
@ReinierTorenbeek Its rsa private key.bguler

1 Answers

1
votes

The test code of Bouncy Castle contains an example of how to read an RSA Private key, in the function ParserTest.doOpenSslRsaTest. Here is a slight modification of that example, it can handle both encrypted and non-encrypted keys as input (and in the latter case, the passphrase will not be used):

private static KeyPair pemRSAP1ReadKeyPair(String pemfilename, String passphrase)
throws FileNotFoundException, IOException
{
    KeyPair result = null;

    FileReader reader = new FileReader(pemfilename);
    PEMParser parser = new PEMParser(reader);
    Object pemobj = parser.readObject();
    parser.close();
    reader.close();

    if (pemobj  == null || 
        !((pemobj instanceof PEMKeyPair) || (pemobj instanceof PEMEncryptedKeyPair))) {
        System.out.println("Unable to read key pair");
    } else {
        PEMKeyPair pemkp;
        if (pemobj instanceof PEMEncryptedKeyPair) {
            PEMEncryptedKeyPair kp = (PEMEncryptedKeyPair)pemobj;
            PEMDecryptorProvider decprov = new BcPEMDecryptorProvider(passphrase.toCharArray());
            pemkp = kp.decryptKeyPair(decprov);
        } else {
            pemkp = (PEMKeyPair)pemobj;
        }
        result = new JcaPEMKeyConverter().setProvider("BC").getKeyPair(pemkp);
    }
    return result;
}

An example for the writer side can be found in AllTests.encryptedTestNew, which roughly looks like this:

private static void pemRSAP8WritePrivateKey(PrivateKey key, String pemfilename, String passphrase)
throws IOException, OperatorCreationException
{
    FileWriter writer = new FileWriter(pemfilename);
    JcaPEMWriter pemwriter = new JcaPEMWriter(writer);

    JceOpenSSLPKCS8EncryptorBuilder encryptorbuilder =
        new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.AES_128_CBC).
            setProvider("BC").
            setPasssword(passphrase.toCharArray());

    OutputEncryptor encryptor = encryptorbuilder.build();
    PKCS8Generator pkcs8 = new JcaPKCS8Generator(key, encryptor);
    pemwriter.writeObject(pkcs8);

    pemwriter.close();
    writer.close();
}

Putting it together to do the conversion:

Security.addProvider(new BouncyCastleProvider());

try {
    KeyPair kp = pemRSAP1ReadKeyPair("rsakey_enc.pem", "changeit");
    PrivateKey privkey = kp.getPrivate();
    if (!(privkey instanceof RSAPrivateKey)) {
        System.out.println("PEM input file does not contain an RSA private key");
    } else {
        pemRSAP8WritePrivateKey(privkey, "rsakey.p8", "abracadabra");
    }    
} catch (Exception e) {
    System.out.println("Caught exception: " + e.getMessage());
}