In this tutorial we will learn how to generate RSA keys in Java and write them to PEM files. BouncyCastle will be used to do this task. BouncyCastle is a library that consist, among others, of a JCE/JCA provider (Java Cryptography Extension/Java Cryptography Architecture) and a set of classes to handle PEM files.

To deal with this tutorial it is required:

  • Maven.
  • JDK 1.6+
  • An IDE, such as Eclipse or Spring Tool Suite.

Table of Contents

1. Create a Maven project

Having Maven installed and its environment variables properly configured, execute the following command in a shell:

mvn archetype:generate -DgroupId=com.txedo.security -DartifactId=bouncycastle-pem-write -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

As result, a Maven project will be created in your current working directory. Finally, import the project in your IDE.

Project structure: Generate RSA keys and write to a PEM file in Java

2. Configure the POM file

Add the BouncyCastle library to the Maven dependencies. In the snippet below, we also added the log4j dependency to print some debug traces in our program.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.txedo.security</groupId>
  <artifactId>bouncycastle-pem-write</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.51</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
  </dependencies>
</project>
  
pom.xml

3. Create a class to encapsulate I/O operations and PEM file handling logic

We have created the class PemFile that encapsulates the creation of a PemObject, included in the BouncyCastle library, and the file write operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.Key;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;

public class PemFile {
  
  private PemObject pemObject;
  
  public PemFile (Key key, String description) {
    this.pemObject = new PemObject(description, key.getEncoded());
  }
  
  public void write(String filename) throws FileNotFoundException, IOException {
    PemWriter pemWriter = new PemWriter(new OutputStreamWriter(new FileOutputStream(filename)));
    try {
      pemWriter.writeObject(this.pemObject);
    } finally {
      pemWriter.close();
    }
  }
}
  
PemFile.java

4. Create the main program class

The main program class responsibility is to create the RSA keys and to orchestrate everything. Optionally, we added the BouncyCastle provider (line 21). The BouncyCastle is used later to get the KeyPairGenerator singleton instance (line 34). Once the keys are created (lines 25-26), the private key and public key are written to the id_rsa and id_rsa.pub files, respectively.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class Main {
  
  protected final static Logger LOGGER = Logger.getLogger(Main.class);
  
  public static final int KEY_SIZE = 1024;

  public static void main(String[] args) throws FileNotFoundException, IOException, NoSuchAlgorithmException, NoSuchProviderException {
    Security.addProvider(new BouncyCastleProvider());
    LOGGER.info("BouncyCastle provider added.");
    
    KeyPair keyPair = generateRSAKeyPair();
    RSAPrivateKey priv = (RSAPrivateKey) keyPair.getPrivate();
    RSAPublicKey pub = (RSAPublicKey) keyPair.getPublic();
    
    writePemFile(priv, "RSA PRIVATE KEY", "id_rsa");
    writePemFile(pub, "RSA PUBLIC KEY", "id_rsa.pub");
  }

  private static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
    generator.initialize(KEY_SIZE);
    
    KeyPair keyPair = generator.generateKeyPair();
    LOGGER.info("RSA key pair generated.");
    return keyPair;
  }

  private static void writePemFile(Key key, String description, String filename)
      throws FileNotFoundException, IOException {
    PemFile pemFile = new PemFile(key, description);
    pemFile.write(filename);
    
    LOGGER.info(String.format("%s successfully writen in file %s.", description, filename));
  }

}
  
Main.java

5. Execute the program

Once the program is executed, we get a console output like this:

Main:26 - BouncyCastle provider added.
Main:42 - RSA key pair generated.
Main:51 - RSA PRIVATE KEY successfully writen in file id_rsa.
Main:51 - RSA PUBLIC KEY successfully writen in file id_rsa.pub.

And two files named id_rsa and id_rsa.pub containing the private key and the public key:

-----BEGIN RSA PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJLORhDfV6VwpZCF
0ZgCKc7cP3Sy5EFkkHY1LKDNqhYmU+ey7GzNjJbm/JIZQwtufcpP8K14kEq2rHo/
F2hN5DQ0hRpSAXljxuz0Y0l5DeELQYrYjcjFMOU5071ebBNuCxm7x3hqSXt/LlmW
GBo73rf3cksI5sxlKEvr69fl4vUJAgMBAAECgYBViTxHzmn56hV9jIrff7suXSPX
8feOpnKJfVgAZXSJrVFL+fNJPcaBkhptYayvt3QxcbxwxoOEFMWQALy5uFCSuWk8
WOiUVlVoCZUjW1fn6z3N0WiuW0yJH315yYjHunFI9THaToIT8XXANZPMS6Jw84Qy
EmNKF6DgirYKvmEyAQJBAORadaff+2yh9r8r25SIIujQpogYMB+JbyAtfSwHMPIC
ZWC137ah1hYj82KutL0yQ9r/6iM+/lY9a5W6SvpWpkECQQCklFfjFxlQ13VrkrGp
h8duqbWm0BdX32lqaTNPscDaz60GWw7LPNhb0LY2mlTP1iSgWdt3VCWKvowHA1Qh
92zJAkANxEJZl5BB0VXd2pgHUVnBbWrMw6CLFi8D4posQFa8EFbqSKyvBvywIwS2
S1AMI+6hUlJcQ5zzuAo3YZ7JjtXBAkARrd3DBzgw9vQmGhv7mhpSSOi6gp//UICC
bcqVRQLyflyX0jBEpMSZGFJ6ixmROe+1SfHJX8Cops9j8XeYLnwBAkEAqxZUZ4NB
kfTwjtxIsZhwaBHKPduFPg+kSKCvTwqpn87D2E0jk/dL4oFk3/otj4L1j1aelFb8
hmciN50QAVL2Bg==
-----END RSA PRIVATE KEY-----
-----BEGIN RSA PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSzkYQ31elcKWQhdGYAinO3D90
suRBZJB2NSygzaoWJlPnsuxszYyW5vySGUMLbn3KT/CteJBKtqx6PxdoTeQ0NIUa
UgF5Y8bs9GNJeQ3hC0GK2I3IxTDlOdO9XmwTbgsZu8d4akl7fy5ZlhgaO96393JL
CObMZShL6+vX5eL1CQIDAQAB
-----END RSA PUBLIC KEY-----

Download the code

The code used in this article to generate RSA keys and write them to a PEM file can be found in GitHub:

References

  1. The Legion of the Bouncy Castle