问题描述
我正在使用 openssl 0.9.6g 并且我已经使用 RSA_generate_key() 创建了公共/私有密钥对.当我用 PEM_write_bio_RSAPublicKey
保存密钥时,它给了我这样的密钥:
I am using openssl 0.9.6g and I have created public/private keypair using RSA_generate_key(). When I save the key with PEM_write_bio_RSAPublicKey
, it gives me keys like:
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
我在 .NET 中有另一个模块,由于其格式,当传入此键时会引发异常.它采用如下格式:
I have another module in .NET which throws an exception when passed in this key due to its format. It takes format like:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
如何将我的密钥转换为这种格式.我正在使用 C++.
How to convert my keys to this format. I am using C++.
在.NET中,我使用的是openssl.net,代码如下:
In .NET, I am using openssl.net, the code is as follows:
string publicKey = @"-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAKGtqUVBBqcGCRYa7Sb6JVQirOX3hggWP2k7CzEtbF/soOONK510Kefm
omXBrGn2t79ES+hAcCvGSiiVZGuEb3UPiznzbiY150SME5nRC+zU0vvdX64ni0Mu
DeUlGcxM1eWSpozO71at6mxLloEMUg0oSWHfAlS5a4LVaURrJqXfAgMBAAE=
-----END RSA PUBLIC KEY-----";
Encoding enc = Encoding.ASCII;
string text = "hello world";
byte[] msg = enc.GetBytes(text);
CryptoKey key = CryptoKey.FromPublicKey(publicKey, "");
RSA rsa = key.GetRSA();
byte[] res = rsa.PublicEncrypt(msg, RSA.Padding.PKCS1);
异常出现:
CryptoKey key = CryptoKey.FromPublicKey(publicKey, "");
如果我使用密钥:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbhcU+fhYmYLESZQAj1hKBXsNY
si0kYHNkxpP7ftxZiTFowWUVXHzQgkcYiCNnp3pt1eG6Vt0WDzyFYXqUUqugvX41
gkaIrKQw/sRiWEx49krcz7Vxr3dufL6Mg3eK7NyWDGsqwFrx/qVNqdhsHg12PGNx
IMY4UBtxin2A8pd4OwIDAQAB
-----END PUBLIC KEY-----
它工作正常.
我一直在寻找这个问题.我想我正在寻找的是如何将 rsa 公钥从 pkcs#1 转换为 x509 格式.
I was looking around for this issue. I think what I am looking for is "how to convert rsa public key from pkcs#1 to x509 format.
推荐答案
我正在使用 openssl 0.9.6g 并且我已经创建了公钥/私钥对使用 RSA_generate_key().它给了我这样的键:
I am using openssl 0.9.6g and I have created public/private keypair using RSA_generate_key(). It gives me keys like:
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
我想我正在寻找的是如何将 rsa 公钥从 pkcs#1 转换为 x509 格式.
I think what I am looking for is "how to convert rsa public key from pkcs#1 to x509 format.
是的,.Net 可以使用一些 ASN.1/DER 编码的密钥和一些 PEM 编码的密钥.区别在于 PKCS 编码与传统编码(OpenSSL 称之为传统").传统的编码是 SubjectPublicKeyInfo,它包括 OID 和公钥.
Yeah, .Net can consume some ASN.1/DER encoded keys, and some PEM encoded keys. The difference is PKCS encoding versus Traditional encoding (OpenSSL calls it "Traditional"). The traditional encoding is the SubjectPublicKeyInfo and it includes the OID and the public key.
因此,您正在寻找写入 SubjectPublicKeyInfo 而不仅仅是公钥的 ASN.1/DER 编码或 PEM 编码.
So you are looking for either an ASN.1/DER encoding or a PEM encoding that writes SubjectPublicKeyInfo, and not just the public key.
我在 .NET 中有另一个模块,它在传入时抛出异常此密钥由于其格式.它采用如下格式:
I have another module in .NET which throws an exception when passed in this key due to its format. It takes format like:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
在这种情况下,使用 PEM_write_bio_PUBKEY
而不是 PEM_write_bio_RSAPublicKey
.
In this case, use PEM_write_bio_PUBKEY
rather than PEM_write_bio_RSAPublicKey
.
PEM_write_bio_PUBKEY
写入SubjectPublicKeyInfo;而 PEM_write_bio_RSAPublicKey
只写入公钥.
PEM_write_bio_PUBKEY
writes the SubjectPublicKeyInfo; while PEM_write_bio_RSAPublicKey
writes only the public key.
您将需要一个 EVP_PKEY
,因此请使用 EVP_PKEY_set1_RSA
进行转换.
You will need an EVP_PKEY
, so use EVP_PKEY_set1_RSA
to convert it.
这是 OpenSSL 中的 PKCS 密钥.它只是公钥.您可以使用 PEM_write_RSAPublicKey
来编写它:
This is a PKCS key in OpenSSL. Its just the public key. You would use PEM_write_RSAPublicKey
to write it:
-----BEGIN RSA PUBLIC KEY-----
这是 OpenSSL 中的传统密钥.它是 SubjectPublicKeyInfo,它包括算法的 OID (rsaEncryption
) 和公钥.您可以使用 PEM_write_bio_PUBKEY
来编写它:
And this is a Traditional key in OpenSSL. Its the SubjectPublicKeyInfo, and it includes an OID for the algorithm (rsaEncryption
) and the public key. You would use PEM_write_bio_PUBKEY
to write it:
-----BEGIN PUBLIC KEY-----
<小时>
不是用PEM_write_RSAPublicKey
保存密钥,你应该用i2d_RSA_PUBKEY_bio
以ASN.1/DER格式写出SubjectPublicKeyInfo结构;或使用 PEM_write_bio_PUBKEY
以 PEM 格式写出.
Instead of saving the key with PEM_write_RSAPublicKey
, you should write out the SubjectPublicKeyInfo structure in ASN.1/DER format with i2d_RSA_PUBKEY_bio
; or write it out in PEM format with PEM_write_bio_PUBKEY
.
下面的程序创建一个 RSA 密钥对,然后写出所有格式的公钥.一定要保存私钥.
The program below creates a RSA key pair, and then writes out the public key in all the formats. Be sure to save the private key, too.
(我很高兴你有 C++ 标签.unique_ptr
让这个练习变得更容易).
(And I'm glad you have the C++ tag. unique_ptr
makes this exercise so much easier).
#include <memory>
using std::unique_ptr;
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/x509.h>
#include <cassert>
#define ASSERT assert
using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
using EVP_KEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
using BIO_FILE_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
int main(int argc, char* argv[])
{
int rc;
RSA_ptr rsa(RSA_new(), ::RSA_free);
BN_ptr bn(BN_new(), ::BN_free);
BIO_FILE_ptr pem1(BIO_new_file("rsa-public-1.pem", "w"), ::BIO_free);
BIO_FILE_ptr pem2(BIO_new_file("rsa-public-2.pem", "w"), ::BIO_free);
BIO_FILE_ptr der1(BIO_new_file("rsa-public-1.der", "w"), ::BIO_free);
BIO_FILE_ptr der2(BIO_new_file("rsa-public-2.der", "w"), ::BIO_free);
rc = BN_set_word(bn.get(), RSA_F4);
ASSERT(rc == 1);
// Generate key
rc = RSA_generate_key_ex(rsa.get(), 2048, bn.get(), NULL);
ASSERT(rc == 1);
// Convert RSA key to PKEY
EVP_KEY_ptr pkey(EVP_PKEY_new(), ::EVP_PKEY_free);
rc = EVP_PKEY_set1_RSA(pkey.get(), rsa.get());
ASSERT(rc == 1);
//////////
// Write just the public key in ASN.1/DER
// Load with d2i_RSAPublicKey_bio
rc = i2d_RSAPublicKey_bio(der1.get(), rsa.get());
ASSERT(rc == 1);
// Write just the public key in PEM
// Load with PEM_read_bio_RSAPublicKey
rc = PEM_write_bio_RSAPublicKey(pem1.get(), rsa.get());
ASSERT(rc == 1);
// Write SubjectPublicKeyInfo with OID and public key in ASN.1/DER
// Load with d2i_RSA_PUBKEY_bio
rc = i2d_RSA_PUBKEY_bio(der2.get(), rsa.get());
ASSERT(rc == 1);
// Write SubjectPublicKeyInfo with OID and public key in PEM
// Load with PEM_read_bio_PUBKEY
rc = PEM_write_bio_PUBKEY(pem2.get(), pkey.get());
ASSERT(rc == 1);
return 0;
}
EVP_PKEY_set1_RSA
中的 set1
会增加引用计数,因此您不会在双重释放时出现段错误.
The set1
in EVP_PKEY_set1_RSA
bumps the reference count, so you don't get a segfault on a double free.
执行程序后,得到预期的PEM和ASN.1/DER:
After executing the program, you get the expected PEM and ASN.1/DER:
$ cat rsa-public-1.pem
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA0cgFv6wEcqoOhPtHdVmX4YFlCwodnSqooeCxFF1XadTS4sZkVJTC
kszHmRqXiXL2NmqnuDQsq6nLd+sNoU5yJJ+W1hwo7UToCyJ/81tS4n6mXvF8oilP
8YudD5QnBdW9LhqttBIN4Gk+Cxun+HG1rSJLGP9yiPPFd7DPiFz0Gd+juyWznWnP
gapDIWEKqANKma3j6b9eopBDWB0XAgU0HQ71MSNbcsPvDd23Ftx0re/7jG53V7Bn
eBy7fQsPmxcn4c74Lz4CvhOr7VdQpeBzNeG2CtkefKWyTk7Vu4FZnAgNd/202XAr
c6GmEQqD2M2zXH/nVZg5oLznECDVQ1x/pwIDAQAB
-----END RSA PUBLIC KEY-----
$ cat rsa-public-2.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0cgFv6wEcqoOhPtHdVmX
4YFlCwodnSqooeCxFF1XadTS4sZkVJTCkszHmRqXiXL2NmqnuDQsq6nLd+sNoU5y
JJ+W1hwo7UToCyJ/81tS4n6mXvF8oilP8YudD5QnBdW9LhqttBIN4Gk+Cxun+HG1
rSJLGP9yiPPFd7DPiFz0Gd+juyWznWnPgapDIWEKqANKma3j6b9eopBDWB0XAgU0
HQ71MSNbcsPvDd23Ftx0re/7jG53V7BneBy7fQsPmxcn4c74Lz4CvhOr7VdQpeBz
NeG2CtkefKWyTk7Vu4FZnAgNd/202XArc6GmEQqD2M2zXH/nVZg5oLznECDVQ1x/
pwIDAQAB
-----END PUBLIC KEY-----
$ dumpasn1 rsa-public-1.der
0 266: SEQUENCE {
4 257: INTEGER
: 00 D1 C8 05 BF AC 04 72 AA 0E 84 FB 47 75 59 97
: E1 81 65 0B 0A 1D 9D 2A A8 A1 E0 B1 14 5D 57 69
: D4 D2 E2 C6 64 54 94 C2 92 CC C7 99 1A 97 89 72
: F6 36 6A A7 B8 34 2C AB A9 CB 77 EB 0D A1 4E 72
: 24 9F 96 D6 1C 28 ED 44 E8 0B 22 7F F3 5B 52 E2
: 7E A6 5E F1 7C A2 29 4F F1 8B 9D 0F 94 27 05 D5
: BD 2E 1A AD B4 12 0D E0 69 3E 0B 1B A7 F8 71 B5
: AD 22 4B 18 FF 72 88 F3 C5 77 B0 CF 88 5C F4 19
: [ Another 129 bytes skipped ]
265 3: INTEGER 65537
: }
0 warnings, 0 errors.
$ dumpasn1 rsa-public-2.der
0 290: SEQUENCE {
4 13: SEQUENCE {
6 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
17 0: NULL
: }
19 271: BIT STRING, encapsulates {
24 266: SEQUENCE {
28 257: INTEGER
: 00 D1 C8 05 BF AC 04 72 AA 0E 84 FB 47 75 59 97
: E1 81 65 0B 0A 1D 9D 2A A8 A1 E0 B1 14 5D 57 69
: D4 D2 E2 C6 64 54 94 C2 92 CC C7 99 1A 97 89 72
: F6 36 6A A7 B8 34 2C AB A9 CB 77 EB 0D A1 4E 72
: 24 9F 96 D6 1C 28 ED 44 E8 0B 22 7F F3 5B 52 E2
: 7E A6 5E F1 7C A2 29 4F F1 8B 9D 0F 94 27 05 D5
: BD 2E 1A AD B4 12 0D E0 69 3E 0B 1B A7 F8 71 B5
: AD 22 4B 18 FF 72 88 F3 C5 77 B0 CF 88 5C F4 19
: [ Another 129 bytes skipped ]
289 3: INTEGER 65537
: }
: }
: }
0 warnings, 0 errors.
<小时>
相关见如何生成RSA私钥使用 openssl?.它向您展示了如何以多种格式编写 RSA 公钥和私钥.
Related, see How to generate RSA private key using openssl?. It shows you how to write a RSA public and private key in a number of formats.
这篇关于在 .Net 中使用 OpenSSL RSA 密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!