How to generate PKCS#1 RSA keys in PEM Format?

50.6k views Asked by At

Sorry for my english and honestly I have a very little understanding on this so please bear with me.

I am developing a java application that sends a signed request to a Server. To do so, I have to generate a PKCS#1 RSA key pair in PEM format for signing and verification. I've tried using OpenSSL v.1.0.1. but the public key generated is a X.509 PEM.

Here's the openssl command I used to generate the keys:

Private Key:

openssl genrsa -out name_of_private_key.pem 1024

Public Key

openssl rsa -in name_of_private_key.pem -pub out > name_of_public_key.pem

I've gone through this thread also and I found an open source JAVA library BouncyCastle: Generating RSA keys in PKCS#1 format in Java

But it says that BouncyCastle is only for PKCS#1 padding not encoding.

Preferably, I'm looking for ways to generate it using JAVA or any third parties if no other option is available.

3

There are 3 answers

3
Naishy On

Although the OpenSSL library supports PKCS#1 encoding, the command line version of OpenSSL will only output RSA Public keys in x.509 format. Unfortunately it seems you are left with no option than to write some code that uses the OpenSSL library to output keys in PKCS#1 format.

For reference, a PKCS#1 key uses these headers/footers:

-----BEGIN RSA PUBLIC KEY----- 
...
-----END RSA PUBLIC KEY-----

Whereas a x.509 key uses these headers/footers:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
2
Dmytro Kutetskyi On

You can force OpenSSH to generate keys in old PEM/PKCS#1 format:
ssh-keygen -t rsa -b 4096 -o -a 100 -f id_rsa -m PEM < /dev/null

5
Joma On

OpenSSL 1.1.1 by default generates Private Key using PKCS#1 standard and encodes in PEM format this is as follows

-----BEGIN RSA PRIVATE KEY----- 
...
-----END RSA PRIVATE KEY-----

You can convert PEM/PKCS#1 key to PEM/PKCS#8 key this is as follows

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

OPENSSL always export Public Key using X.509 standard and encodes in PEM format
this is as follows

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

I use these scripts for generate RSA keypair.

Powershell - CreateKeyPair.ps1

Set-Alias openssl "C:\Program Files\OpenSSL-Win64-1-1-1\bin\openssl.exe"

openssl version

Write-Host "=== GENERATE PRIVATE KEY --- Format: PKCS#1 --- File: private.txt==="
openssl genrsa -f4 -out private.txt 4096 

Write-Host "=== GENERATE PRIVATE KEY --- Format: PKCS#8 --- File: private8.txt==="
openssl pkcs8 -topk8 -inform pem -in private.txt -outform PEM -nocrypt -out private8.txt

Write-Host "=== GENERATE PUBLIC KEY --- Format: X.509 --- File: public.txt==="
openssl rsa -in private.txt -outform PEM -pubout -out public.txt

PowerShell - OpenSSL 1.1.1

CMD - CreateKeyPair.bat

@ECHO OFF
set openssl="C:\Program Files\OpenSSL-Win64-1-1-1\bin\openssl.exe"

%openssl% version

ECHO "=== GENERATE PRIVATE KEY --- Format: PKCS#1 --- File: private.txt==="
%openssl% genrsa -f4 -out private.txt 4096 

ECHO "=== GENERATE PRIVATE KEY --- Format: PKCS#8 --- File: private8.txt==="
%openssl% pkcs8 -topk8 -inform pem -in private.txt -outform PEM -nocrypt -out private8.txt

ECHO "=== GENERATE PUBLIC KEY --- Format: X.509 --- File: public.txt==="
%openssl% rsa -in private.txt -outform PEM -pubout -out public.txt

cmd - OpenSSL 1.1.1

███████████████████

In OpenSSL3.0 the command genrsa is deprecated, instead of this we need to use genpkey. OpenSSL 3.0 by default generates Private Key using PKCS#8 standard and encodes in PEM format

I use these scripts for generate RSA keypair.

Powershell - CreateKeysOpenSSL3.0.ps1

Set-Alias openssl "C:\Program Files\OpenSSL-Win64\bin\openssl.exe"

openssl version

Write-Host "=== GENERATE PRIVATE KEY --- Format: PEM/PKCS#8 --- File: private.txt==="
openssl genpkey -out private.txt -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:4096

Write-Host "=== GENERATE PUBLIC KEY --- Format: PEM/X.509 --- File: public.txt==="
openssl pkey -inform PEM -outform PEM -in private.txt -pubout -out public.txt 

PowerShell - OpenSSL3.0

CMD- CreateKeysOpenSSL3.0.bat

@ECHO OFF
set openssl="C:\Program Files\OpenSSL-Win64\bin\openssl.exe"

%openssl% version

ECHO "=== GENERATE PRIVATE KEY --- Format: PEM/PKCS#8 --- File: private.txt==="
%openssl% genpkey -out private.txt -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:4096


ECHO "=== GENERATE PUBLIC KEY --- Format: PEM/X.509 --- File: public.txt==="
%openssl% pkey -inform PEM -outform PEM -in private.txt -pubout -out public.txt

CMD - OpenSSL3.0

███████████████████

Generate from Java - Private PEM/PKCS#8 and Public PEM/X.509
you can TEST/RUN this CODE in https://replit.com/@JomaCorpFX/JavaPemRsaKeyPair#Main.java

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.util.Base64;

public class Main {


    private static final String RsaPemPrivateKeyInitialString = "-----BEGIN PRIVATE KEY-----";
    private static final String RsaPemPrivateKeyFinalString = "-----END PRIVATE KEY-----";
    private static final String RsaPemPublicKeyInitialString = "-----BEGIN PUBLIC KEY-----";
    private static final String RsaPemPublicKeyFinalString = "-----END PUBLIC KEY-----";
    private static final int PEM_LINE_LEN = 64;

    public static String InsertLineBreaks(String data, int lineBreaksLength)
    {
        StringBuilder sb = new StringBuilder();
        int Segments = data.length() / lineBreaksLength;
        if (Segments < 0)
        {
            return data;
        }
        else
        {
            for (int i = 0; i < Segments; i++)
            {
                sb.append(data.substring(i * lineBreaksLength, i*lineBreaksLength + lineBreaksLength));
                sb.append(System.lineSeparator());
            }
            if (Segments * lineBreaksLength < data.length())
            {
                sb.append(data.substring(Segments * lineBreaksLength));
                sb.append(System.lineSeparator());
            }
            return sb.toString().trim();

        }
    }

    public static RsaKeyPair createKeyPair(int keySize) throws Exception {
        RsaKeyPair result = new RsaKeyPair();
        KeyPairGenerator MyKeyPairGenerator = KeyPairGenerator.getInstance("RSA");
        MyKeyPairGenerator.initialize(keySize, new SecureRandom());
        KeyPair MyKeyPair = MyKeyPairGenerator.generateKeyPair();

        result.setPublicKey(RsaPemPublicKeyInitialString + System.lineSeparator() + InsertLineBreaks(Base64.getEncoder().encodeToString(MyKeyPair.getPublic().getEncoded()), PEM_LINE_LEN)  + System.lineSeparator() + RsaPemPublicKeyFinalString);
        result.setPrivateKey(RsaPemPrivateKeyInitialString + System.lineSeparator() + InsertLineBreaks(Base64.getEncoder().encodeToString(MyKeyPair.getPrivate().getEncoded()),PEM_LINE_LEN) + System.lineSeparator() + RsaPemPrivateKeyFinalString);
        return result;
    }

    public static void main(String[] args) throws Exception {
        RsaKeyPair keyPair = createKeyPair(4096);
        System.out.println(keyPair.toString());

    }

    public static class RsaKeyPair
    {

        private String PublicKey;
        private String PrivateKey;

        public RsaKeyPair()
        {
        }

        public RsaKeyPair(String PublicStringKey, String PrivateStringKey)
        {
            this.PublicKey = PublicStringKey;
            this.PrivateKey = PrivateStringKey;
        }

        public String getPublicKey()
        {
            return PublicKey;
        }

        public void setPublicKey(String PublicStringKey)
        {
            this.PublicKey = PublicStringKey;
        }

        public String getPrivateKey()
        {
            return PrivateKey;
        }

        public void setPrivateKey(String PrivateStringKey)
        {
            this.PrivateKey = PrivateStringKey;
        }

        @Override
        public String toString()
        {
            return String.format("Public\n%s\nPrivate\n%s", PublicKey, PrivateKey);
        }
    }
}

Output

Public
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz/hDwUW560ADH74ejSUh
CVfdkJyLX9MlqkIanMgsRnVGqzc2Mz9flpsphOJvDVsWJ2IMkDgZAKZ0foqKve+4
UuOLDjEIogIsNCU0w5Bkqct4YMsR24kGem6zm/40IG+yFtRWEb7DEzrYt6bJ6S24
KvWxFN0YmIAg1QLVYinB3qtXdbyzGBtn/rY+0Dir/C2nibuafcitmmOgY4rocXIr
BZlui+zUyoml8r8LcWScpwWcx35gqaxw7E5ayUOdGDViPJyFg0Hs5p6RtttWCA2W
YILVf/4NRJj5gp293PQECeHlBOSqBzJDIZfF7aWi3/qdClMxKL5RSFCqLaYeIh5p
Fl+L5y4lHWnsNipppaqZlTw+wHrl3eVSCmMlQXC9yRMedzIqejXWDl1QN+FSpcaQ
8pfyfhPzbT8v+DICff9K2IjQcA/4eew0qNcdd0FKYaFoViQ7nT91kS9E+vTf5v16
/KQlNX0ywNIHPcku7VMZ5a5/9oEJPGcL8hFExHIEtWwcJ+zcrk5srNEBp4xgWaKv
nIUfhJJfqZ3huCT0eRxbdq9yQ0qdRo0Rc1w/LnKs9OKH6D8WMyJs5qQwuk+vIjSx
MZWjVIt6r11vrE9ySwO/V4IjrQnb/KjflzkOqIhEbEjpnnwqreSxvwKhRvvBauFw
EEuL16QpSo54H5JDLgh4dyMCAwEAAQ==
-----END PUBLIC KEY-----
Private
-----BEGIN PRIVATE KEY-----
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
z3YIPsJ7PD4BGnEaBg0eMq72qTrD
-----END PRIVATE KEY-----

output