11

对不起我的英语,老实说我对此知之甚少,所以请多多包涵。

我正在开发一个向服务器发送签名请求的 java 应用程序。为此,我必须生成格式为PKCS#1 RSA密钥对以PEM进行签名和验证。我试过使用OpenSSL v.1.0.1。但生成的公钥是X.509 PEM.

这是我用来生成密钥的 openssl 命令:

私钥

openssl genrsa -out name_of_private_key.pem 1024

公钥

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

我也浏览了这个线程,我发现了一个开源 JAVA 库 BouncyCastle:Generating RSA keys in PKCS#1 format in Java

但它说 BouncyCastle 仅用于 PKCS#1填充而不是编码

最好,如果没有其他选项可用,我正在寻找使用 JAVA 或任何第三方生成它的方法。

4

3 回答 3

17

默认情况下, OpenSSL 1.1.1使用PKCS#1标准生成私钥并以PEM格式编码,如下所示

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

您可以将PEM/PKCS#1密钥转换为PEM/PKCS#8密钥,如下所示

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

OPENSSL始终使用X.509标准导出公钥并以PEM格式编码, 如下所示

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

我使用这些脚本来生成 RSA 密钥对。

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

███████████████████</h1>

OpenSSL3.0中,命令genrsa已被弃用,我们需要使用genpkey代替它。 OpenSSL 3.0默认使用PKCS#8标准生成私钥并以PEM格式编码

我使用这些脚本来生成 RSA 密钥对。

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

███████████████████</h1>

从 Java 生成 - Private PEM/PKCS#8 和 Public PEM/X.509
您可以在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);
        }
    }
}

输出

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-----

输出

于 2016-11-28T00:00:22.383 回答
8

虽然 OpenSSL 库支持 PKCS#1 编码,但 OpenSSL 的命令行版本只会输出 x.509 格式的 RSA 公钥。不幸的是,您似乎别无选择,只能编写一些使用 OpenSSL 库以 PKCS#1 格式输出密钥的代码。

作为参考,PKCS#1 密钥使用以下页眉/页脚:

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

而 x.509 键使用这些页眉/页脚:

-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
于 2013-04-23T14:11:08.983 回答
0

您可以强制 OpenSSH 生成旧 PEM/PKCS#1 格式的密钥:
ssh-keygen -t rsa -b 4096 -o -a 100 -f id_rsa -m PEM < /dev/null

于 2021-03-18T18:37:13.840 回答