how to generate public and private key in PEM format
Asked Answered
S

4

10

I need to generating a RSA and DSA key pair (public and private key) in PEM format using java. I want the public and private key files to be opened with this format:

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO 3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX 7O9D22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK48bn+v1oZHCM0nYQ2NqUkvS j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd OrUZ/wK69Dzu4IvrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ 5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl FQIDAQAB -----END PUBLIC KEY-----

My public key is already generated before with this format that i do not want it:

0Ÿ0 *†H†÷ 0Ÿ0 *†H†÷

ok, this is my code of key generation:

private static void createKey()
        throws Exception {

            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            System.out.print("Password to encrypt the private key: ");
            String password = in.readLine();
            System.out.println("Generating an RSA keypair...");

            // Create an RSA key
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.genKeyPair();

            System.out.println("Done generating the keypair.\n");

            // Now we need to write the public key out to a file
            System.out.print("Public key filename: ");
            String publicKeyFilename = "C:/Users/Joe/Desktop/" + in.readLine();

            // Get the encoded form of the public key so we can
            // use it again in the future. This is X.509 by default.
            byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

            // Write the encoded public key out to the filesystem
            FileOutputStream fos = new FileOutputStream(publicKeyFilename);
            fos.write(publicKeyBytes);
            fos.close();

            // Now we need to do the same thing with the private key,
            // but we need to password encrypt it as well.
            System.out.print("Private key filename: ");
            String privateKeyFilename = "C:/Users/Joe/Desktop/" + in.readLine();

            // Get the encoded form. This is PKCS#8 by default.
            byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

            // Here we actually encrypt the private key
            byte[] encryptedPrivateKeyBytes =
            passwordEncrypt(password.toCharArray(),privateKeyBytes);

            fos = new FileOutputStream(privateKeyFilename);
            fos.write(encryptedPrivateKeyBytes);
            fos.close();
        }

thank you for your help..

Saintpierre answered 15/12, 2013 at 18:32 Comment(6)
Care to show us what you've done so far?Benoite
u can check it please..Saintpierre
Please edit it into your question, instead of providing it as an answer, since it's part of the problem, not the solution.Benoite
ok done, u can check itSaintpierre
Why do you want to do this in Java? There's no need to do so.Embodiment
i'm doing an interface for an encryption software project, and my professor at university want it..Saintpierre
A
11

Instead of manually generating the PEM String, you can use the bouncy castle to do it for you: since it's a tested library you can be sure about the output. The following code is in Kotlin but can easily be used with Java syntax:

        val gen = KeyPairGenerator.getInstance("RSA")
        gen.initialize(2048)
        val pair = gen.generateKeyPair()
        val privateKey: PrivateKey = pair.private
       
  
        val pemObject = PemObject("RSA PRIVATE KEY", privateKey.encoded)
        
        val byteStream = ByteArrayOutputStream()
        val pemWriter = PemWriter(OutputStreamWriter(byteStream))
        pemWriter.writeObject(pemObject)
        pemWriter.close();
        println(String(byteStream.toByteArray()))

Ailis answered 25/6, 2020 at 9:12 Comment(0)
D
5

Maybe a bit late but there is my solution. Hope it helps others.

byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

Here you're taking bytes of key and writing directly to file. So you get the appropriate result - DER-encoded file. However PEM is Base64 encoded format with line breaks each 64 symbols and header/footer.

There is code implementing this logic:

String publicKeyContent = Base64.getEncoder().encodeToString(publicKeyBytes);
String publicKeyFormatted = "-----BEGIN PUBLIC KEY-----" + System.lineSeparator();
for (final String row: 
        Splitter
            .fixedLength(64)
            .split(publicKeyContent)
    ) 
{
    publicKeyFormatted += row + System.lineSeparator();
}
publicKeyFormatted += "-----END PUBLIC KEY-----";

So publicKeyFormatted will contain PEM-encoded string of public key.

P.S. Splitter is a class provided in Guava lib, but you can split the string with a simple cycle or somehow.

Derogatory answered 29/5, 2018 at 10:21 Comment(1)
Base64 does not have direct encode function.Boschvark
L
2

Java version of @Syd Gillani 's answer:

NOTE: you will need org.bouncycastle bcprov-jdk18on dependency

var gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
var pair = gen.generateKeyPair();

var rsaPrivateKey = (RSAPrivateKey) pair.getPrivate(); 
var pemObject = new PemObject("PRIVATE KEY", rsaPrivateKey.getEncoded());

var byteStream = new ByteArrayOutputStream();
var pemWriter = new PemWriter(new OutputStreamWriter(byteStream));
pemWriter.writeObject(pemObject);
pemWriter.close();

System.out.println(new String(byteStream.toByteArray()));

The output will then be usable with other tools like java lib com.nimbusds.jose.jwk.JWK for parsing it in JWK format

Ligroin answered 15/5 at 17:5 Comment(0)
S
0

I've written a library that includes methods which can do this. It's called Reasonably Easy Cryptography and you can use the PEMHandler methods for this. Here's how you could do it, assuming you've imported PEMHandler from my library, and that key's class is an implementation of java.security.Key such as a PrivateKey:

String pem = PEMHandler.keyToPem(key);

This works with any kind of Key, it'll figure out whether it's a public or private key and what algorithm it uses on its own (it isn't perfect and I'm still working on finding the best way to do that, but it does work fine with PrivateKey and PublicKey). There's also a method to do this for both keys in a KeyPair in one call, and methods to convert the PEM string back to a Key.

Sneaking answered 9/4, 2022 at 17:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.