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

3

16

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.

Laraelaraine answered 28/5, 2012 at 10:49 Comment(1)
Please post the answer so that it can help others.Chalcedony
R
22

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

Reaganreagen answered 28/11, 2016 at 0:0 Comment(5)
I think you've mixed up public and private. openssl genrsa (and pkey -traditional in 1.1.0 only) writes 'RSA PRIVATE KEY' which is PKCS1, while pkcs8 -topk8, pkey (default), genpkey, and req -newkey write 'PRIVATE KEY' or 'ENCRYPTED PRIVATE KEY' which are both PKCS8. But all commandline operations except rsa -RSAPublicKey_out write 'PUBLIC KEY' which is as you say X.509 SPKI. This Q asked about public key not private.Gustatory
Thanks for your correction... Changed -----BEGIN RSA PUBLIC KEY----- with correct -----BEGIN RSA PRIVATE KEY-----Reaganreagen
This answer is still wrong. It has many upvotes, but the PUBLIC KEY generated is an X.509 SubjectPublicKeyInfo, which may contain the RSA PUBLIC KEY in PKCS#1 format, but it isn't the same at all. This is just a key pair generation followed by the usual exports, nothing of interest.Asteroid
Simply changing the header DOES NOT convert between PKCS#1 and PKCS#8. In fact, doing so may prevent many programs from correctly recognizing the structure of the keys, because those programs rely on the header to determine what structure (PKCS#1 or PKCS#8 for instance) to expect.Lewan
I downvoted (and commented) because of this line "You can convert PEM/PKCS#1 key to PEM/PKCS#8 key this is as follows". This seems to indicate changing the header changes the structure (PKCS#1 to PKCS#8). Love it when people say "this is from year XXXX". Answers don't go bad or go away after time, people still read them ;)Lewan
A
8

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-----
Asteria answered 23/4, 2013 at 14:11 Comment(3)
Actually commandline rsa does support this format with options -RSAPublicKey_{in,out} since 1.0.0 in 2010, but this wasn't documented until 1.0.1f in 2014 and not in the usage msg until 1.1.0 in 2016 :{ In 0.9.8 you could use asn1parse with -strparse to locate and extract the PKCS1 part of SPKI as DER, and then use enc -base64 and a little text editing to convert DER to PEM. OTOH OP preferred Java and #14052985 answered that in Dec. 2012.Gustatory
Could you put this in a separate answer? I think it needs to be upvoted & accepted as correct answer, instead of the other ones by now.Asteroid
openssl.org/docs/manmaster/man1/openssl-pkcs8.htmlTheurer
H
2

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

Hibernate answered 18/3, 2021 at 18:37 Comment(2)
Only the privatekey, and any version that supports -m PEM for this (since 8.0 in 2019, 7 years after the Q) does not need -o under any circumstances, and ignores -a N for 'old'=PKCS1 format. For publickey OpenSSH always did and still does use its own format which is neither PKCS1 nor X.509.Gustatory
The command line parameter "-m PEM" is the secret sauce. This worked for me.Immobilize

© 2022 - 2024 — McMap. All rights reserved.