如何使用 OpenSSL 生成 RSA 私钥?
Posted
技术标签:
【中文标题】如何使用 OpenSSL 生成 RSA 私钥?【英文标题】:How to generate RSA private key using OpenSSL? 【发布时间】:2011-08-21 02:15:44 【问题描述】:我想知道如何在我的 C 源文件中使用 OpenSSL 库生成 RSA 私钥。我知道如何使用终端命令生成它。
其实我的 server.c 文件会生成一个私钥并发送到 client.c 如果可能,请帮助我提供一些源代码,否则将不胜感激。
我正在使用 Linux 机器。
【问题讨论】:
【参考方案1】:#include <openssl/rsa.h>
#include <openssl/pem.h>
const int kBits = 1024;
const int kExp = 3;
int keylen;
char *pem_key;
RSA *rsa = RSA_generate_key(kBits, kExp, 0, 0);
/* To get the C-string PEM form: */
BIO *bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(bio, rsa, NULL, NULL, 0, NULL, NULL);
keylen = BIO_pending(bio);
pem_key = calloc(keylen+1, 1); /* Null-terminate */
BIO_read(bio, pem_key, keylen);
printf("%s", pem_key);
BIO_free_all(bio);
RSA_free(rsa);
free(pem_key);
【讨论】:
RSA_generate_key
已弃用;您应该改用 RSA_generate_key_ex
。请参阅 RSA_generate_key
的手册页
不需要先初始化库吗?【参考方案2】:
我想知道如何在我的 c 源文件中使用 openssl 库生成 RSA 私钥?
生成密钥很容易。只需使用RSA_generate_key_ex
。下面的程序向您展示了如何做到这一点。
保存公钥和私钥是另一回事,因为您需要知道格式。下面的程序向您展示了如何以多种格式执行此操作。
这里有各种功能和格式。
相关,请参阅What is the differences between “BEGIN RSA PRIVATE KEY” and “BEGIN PRIVATE KEY”。它讨论了SubjectPublicKeyInfo、PrivateKeyInfo以及公钥和私钥之间的区别。
PEM_write_bio_RSAPublicKey(PKCS PEM 格式)。通知BEGIN RSA PUBLIC KEY
:
$ cat rsa-public-1.pem
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAmkD+kwlbsmvyUYOBuVkyWDyBNxGQNJrKUZu97Z+hBG3OA85fY6oV
CdyoT+KDmtAFgTgY76KRkHVYQH3HYFpec5vNptLJNd6OVJCXR6NFUR2b7aHLkres
qyPMrAHNU16wp85qdHALNd72EoUPkVItHqaBOldx7J9vyUF3bpAWq4XxRlbiK9iv
Yuci4/jr4ppRoso6LZm9Inzm53zYt2AqHUZQ+3WgK+czZyk8tLGEN7rtLZ7opvVA
aAiRGWiUWACtRwmpAq2L5PuWZkYdQ7WQigkx5c3x8iBkeEh022zqYkGOTh2Ue4Uf
rIYuSqjLb2d+jkfZQ1S4LQLQPtMxNV/FqwIDAQAB
-----END RSA PUBLIC KEY-----
PEM_write_bio_PUBKEY(传统 PEM 格式)。通知BEGIN PUBLIC KEY
:
$ cat rsa-public-2.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmkD+kwlbsmvyUYOBuVky
WDyBNxGQNJrKUZu97Z+hBG3OA85fY6oVCdyoT+KDmtAFgTgY76KRkHVYQH3HYFpe
c5vNptLJNd6OVJCXR6NFUR2b7aHLkresqyPMrAHNU16wp85qdHALNd72EoUPkVIt
HqaBOldx7J9vyUF3bpAWq4XxRlbiK9ivYuci4/jr4ppRoso6LZm9Inzm53zYt2Aq
HUZQ+3WgK+czZyk8tLGEN7rtLZ7opvVAaAiRGWiUWACtRwmpAq2L5PuWZkYdQ7WQ
igkx5c3x8iBkeEh022zqYkGOTh2Ue4UfrIYuSqjLb2d+jkfZQ1S4LQLQPtMxNV/F
qwIDAQAB
-----END PUBLIC KEY-----
PEM_write_bio_PrivateKey (PEM)。通知BEGIN PRIVATE KEY
:
$ cat rsa-private-1.pem
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaQP6TCVuya/JR
g4G5WTJYPIE3EZA0mspRm73tn6EEbc4Dzl9jqhUJ3KhP4oOa0AWBOBjvopGQdVhA
fcdgWl5zm82m0sk13o5UkJdHo0VRHZvtocuSt6yrI8ysAc1TXrCnzmp0cAs13vYS
hQ+RUi0epoE6V3Hsn2/JQXdukBarhfFGVuIr2K9i5yLj+OvimlGiyjotmb0ifObn
fNi3YCodRlD7daAr5zNnKTy0sYQ3uu0tnuim9UBoCJEZaJRYAK1HCakCrYvk+5Zm
Rh1DtZCKCTHlzfHyIGR4SHTbbOpiQY5OHZR7hR+shi5KqMtvZ36OR9lDVLgtAtA+
0zE1X8WrAgMBAAECggEAWybDCJJEHGgLdj22v5dE171RQgBf7aX2nkjg7/UfSiW0
0qz100gjTIOW9jXNPQNl7Vj/60NuryWYc+ufkIF2ROyxlr4CZpHQG4qhypRhlrBf
fwnX6Sgeobby8EXUVkqjK1YftBStmzTYxlLYwzADN5R+0sHvsTr57LyB3dTJgKsn
4iAuJXfR4EthZ6iEM+D8FrmXt5lJ2d1FoMLKiC09M7nMuY9ARqR6O5Tr/Tq4vqfw
La6Mv3mWrD2nIznyTJtxUkAxvCRi1tfHOw2YCl6u2JqqWRjLBeaGNyydhGeVH5PT
utPHtDciCxpUgGuQ8wNBEstiGYXklpLJFS48+bWVCQKBgQDLC4DNeZ/Tc9g+WUFU
ypVCTKfCYt2YmLcNeKDqIPdt14PmV3odIxZGJ1OWrNK1LA50pet0xxY1HRjcBsN+
XUIc5Xa/0nWazdz7c0nqzZgOpVYfPcApQ1K/dqsoWzRY+rlz2PEOYJwMaKW/kkVV
8EPEg38Ck/qr5iKsBYljTteHhQKBgQDCe+iKtPjlFPJ4WX8vTu5QVpRjYmqj87/j
4JFpSh7Lv2PsxSCGQR/7JoyB8Zaz9dyP+RV8/ySJuwGqSseU+W495h8oHe1DtIxU
lTR1GB4YI4BU+txvydzQiaFyEUdEFqJblCxXg+XDAcwCUYESLbR661ljbVV/0Qep
HMTeXgfnbwKBgDPMYHSK1ZItGHp3bKpD8CX0xktZy2xVcUV3g52XAWg9NcH6iQWL
4O/Oso1a03oynhF2DoZBD9JG9QOUmiTPh8E1bMDs4OG4KOrg83d6MZNy7HCV4ULl
kOOVU369HbKha9Q5AO4JCWZFABvKJfQRkkg8v5cZxzY5RJkb5Hu4LlW9AoGACvxg
2GT8okQapj23934n7BXX7/1BNN2x+zdWP3JWZv/6rwc7nRnUqqU0zqpM7wF2YhOZ
6SOodrc/ktUCjSHB3nE/VU7LdkWen7CF9A9Ws9pdh29cQFxQwt7jZcQgGHKG3VFz
Z8Yllmxlj8P23IYEaeUdeYZVjBDMs/rSDBWXsLUCgYEAw4TTKH/4BdnRIKhNLp63
n8oGo7Cc/idSQD8XbUVpPbLmychOs2no3Y0XT+xRTAuXjm0GYdmY3Sk3/polGMu5
NHmi5293eAxJ+9ikSD+bYCaLCXFI2PmgJkm+uS1WucqQOSAKOXS6mfsv2pn9YXKw
QCMIqX4p7BmO7OD1CFEu6ho=
-----END PRIVATE KEY-----
PEM_write_bio_PKCS8PrivateKey (PEM)。通知BEGIN PRIVATE KEY
:
$ cat rsa-private-2.pem
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaQP6TCVuya/JR
g4G5WTJYPIE3EZA0mspRm73tn6EEbc4Dzl9jqhUJ3KhP4oOa0AWBOBjvopGQdVhA
fcdgWl5zm82m0sk13o5UkJdHo0VRHZvtocuSt6yrI8ysAc1TXrCnzmp0cAs13vYS
hQ+RUi0epoE6V3Hsn2/JQXdukBarhfFGVuIr2K9i5yLj+OvimlGiyjotmb0ifObn
fNi3YCodRlD7daAr5zNnKTy0sYQ3uu0tnuim9UBoCJEZaJRYAK1HCakCrYvk+5Zm
Rh1DtZCKCTHlzfHyIGR4SHTbbOpiQY5OHZR7hR+shi5KqMtvZ36OR9lDVLgtAtA+
0zE1X8WrAgMBAAECggEAWybDCJJEHGgLdj22v5dE171RQgBf7aX2nkjg7/UfSiW0
0qz100gjTIOW9jXNPQNl7Vj/60NuryWYc+ufkIF2ROyxlr4CZpHQG4qhypRhlrBf
fwnX6Sgeobby8EXUVkqjK1YftBStmzTYxlLYwzADN5R+0sHvsTr57LyB3dTJgKsn
4iAuJXfR4EthZ6iEM+D8FrmXt5lJ2d1FoMLKiC09M7nMuY9ARqR6O5Tr/Tq4vqfw
La6Mv3mWrD2nIznyTJtxUkAxvCRi1tfHOw2YCl6u2JqqWRjLBeaGNyydhGeVH5PT
utPHtDciCxpUgGuQ8wNBEstiGYXklpLJFS48+bWVCQKBgQDLC4DNeZ/Tc9g+WUFU
ypVCTKfCYt2YmLcNeKDqIPdt14PmV3odIxZGJ1OWrNK1LA50pet0xxY1HRjcBsN+
XUIc5Xa/0nWazdz7c0nqzZgOpVYfPcApQ1K/dqsoWzRY+rlz2PEOYJwMaKW/kkVV
8EPEg38Ck/qr5iKsBYljTteHhQKBgQDCe+iKtPjlFPJ4WX8vTu5QVpRjYmqj87/j
4JFpSh7Lv2PsxSCGQR/7JoyB8Zaz9dyP+RV8/ySJuwGqSseU+W495h8oHe1DtIxU
lTR1GB4YI4BU+txvydzQiaFyEUdEFqJblCxXg+XDAcwCUYESLbR661ljbVV/0Qep
HMTeXgfnbwKBgDPMYHSK1ZItGHp3bKpD8CX0xktZy2xVcUV3g52XAWg9NcH6iQWL
4O/Oso1a03oynhF2DoZBD9JG9QOUmiTPh8E1bMDs4OG4KOrg83d6MZNy7HCV4ULl
kOOVU369HbKha9Q5AO4JCWZFABvKJfQRkkg8v5cZxzY5RJkb5Hu4LlW9AoGACvxg
2GT8okQapj23934n7BXX7/1BNN2x+zdWP3JWZv/6rwc7nRnUqqU0zqpM7wF2YhOZ
6SOodrc/ktUCjSHB3nE/VU7LdkWen7CF9A9Ws9pdh29cQFxQwt7jZcQgGHKG3VFz
Z8Yllmxlj8P23IYEaeUdeYZVjBDMs/rSDBWXsLUCgYEAw4TTKH/4BdnRIKhNLp63
n8oGo7Cc/idSQD8XbUVpPbLmychOs2no3Y0XT+xRTAuXjm0GYdmY3Sk3/polGMu5
NHmi5293eAxJ+9ikSD+bYCaLCXFI2PmgJkm+uS1WucqQOSAKOXS6mfsv2pn9YXKw
QCMIqX4p7BmO7OD1CFEu6ho=
-----END PRIVATE KEY-----
PEM_write_bio_RSAPrivateKey (PEM)。通知BEGIN RSA PRIVATE KEY
:
$ cat rsa-private-3.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtRZEW6EXwMv2j4mZOhPv3GHcVTi2k8rNlaHc//wUfIYxmNPE
zzPd0JBUyT/dbRzwrPMrnmzgdFRidbpyplatCNhq+Httog+Cxd6MdxqGAqOI/X5p
6uxFK8/ptR7E84XpclUQSw+X8VxaG4SFDeMYAuGgw4bIezfFoIySdL16UVIjtSzj
aRoG1R8kZFtfKONukoqmQUPwFpLvbxE0u6/pzWk873EiM9w6+zZ3c4NAc0ehzfzA
0maQfjbmVSRihplbocreRXLCaaCYUqAf0K3l4NOYBzVOxBeG03wzsZ0J+nWc5zIW
b6auwqBYTO7gMRFXO5vFQZXKaSsEc+B/KwztUwIDAQABAoIBAQCjKDTe+f4Uz7CP
E0LjeSMcRW/nuPmHn6orr3MXkWBD8gSt1d/1cJ3iVKiPyuMOdIzExzP9wctaBM3R
lPPHu0CcP6Hh0BOveJoy/ZlBlrw3lHDRNRzpdYe9Oc8wSVDauUTkpo/PkXUtGjB1
qqjXIk14CyJ2CPKJUm7VgNJULIQQz5Uh7rMZjK1FvlcLU+v06nHHC4y0w9X/ygXq
UoFKKlEADcPqHR/imhrozQxqC4wtn6xFiT/cDngazoGqMX5NCZpso1OZChu3vdAa
PYOz/Wv22C+JIK0xgDIfgTh01IyAedeI2ABQeKrak0nU6Faer2Y6cMvHhidG95/v
lmIfSqwBAoGBANroQDoZDVYQ7ToYPNd9MIgb217Ug7I6j/NEpGJjUktxeRzgZKDv
U5rdbaAArhLXY4FZ0UTZ3WytN1wwV1yXo3Ey5l5CzCXN4GYmv41Z57D218fE7mnx
T8OKD4SxznYcayCWtbjlTXC13rz3gYT3XgyKwTpuywabhOMjDpaos+wTAoGBANPF
c2uTIPNq+RUouqTnxyBg+/ujwcF32F5n2Rad9cv1NdtZ22JdotKIpSEnvifqbtGG
od7vWg5gWgtoG67852K5Q5oBELkcPz4r9PmbSo9H9VWuYotCwB3hvZnIA5GFkfW6
7pLY3j1gdLqMUm0yHPx4or53ScgU9pnYRFJ6UKHBAoGATTE05MfMwhq57JB7c+l7
YaOhGbGKtyCbfkcoSGGJtXzQHnSqR23dZ3DJpXBX8eDt/8DyYHsK77WtHd8WD1qR
ketG/NpFLteIV702MtwPLYH92T4CbG1hmSxoCHzCtzeSNy2t6wNA6YvYfX4xt/ea
vIV5WeeTxEK2+3lzPYFD4O0CgYA+KGJsXM77I5bgowfFh1JnKpBLmBEy3B5h91E8
1jhjGSIptAI0qQ81hG4TgTrLNIA6d63jZZWlSpqjZndZsVmpHH+/IDjsXGIjuXs6
GF6WF6Tm9Txva7RAERY5oP+LIw1odum3qHfyw/D/IFjBPEhNworiJNk/JQgMt/G1
07j/AQKBgHF2AoovqkCVx0TyggVkwBxwrQvR4jmUYmLKYWYc+IkDQzESXIUme61b
OZ7OfbTKQHBTz7i8bXK5mWSbNgmhcVsKHnbPyXKIrL7p+j2b2gdSNAaP1c5XFI/l
BvQSuumzUXbzQHbsYjn/4phOv3AK1xGLhnVI69QpaCYYuuPyfm1X
-----END RSA PRIVATE KEY-----
i2d_RSAPublicKey_bio(ASN.1/DER):
$ dumpasn1 rsa-public.der
0 266: SEQUENCE
4 257: INTEGER
: 00 9A 40 FE 93 09 5B B2 6B F2 51 83 81 B9 59 32
: 58 3C 81 37 11 90 34 9A CA 51 9B BD ED 9F A1 04
: 6D CE 03 CE 5F 63 AA 15 09 DC A8 4F E2 83 9A D0
: 05 81 38 18 EF A2 91 90 75 58 40 7D C7 60 5A 5E
: 73 9B CD A6 D2 C9 35 DE 8E 54 90 97 47 A3 45 51
: 1D 9B ED A1 CB 92 B7 AC AB 23 CC AC 01 CD 53 5E
: B0 A7 CE 6A 74 70 0B 35 DE F6 12 85 0F 91 52 2D
: 1E A6 81 3A 57 71 EC 9F 6F C9 41 77 6E 90 16 AB
: [ Another 129 bytes skipped ]
265 3: INTEGER 65537
:
0 warnings, 0 errors.
i2d_RSAPrivateKey_bio(ASN.1/DER):
$ dumpasn1 rsa-private.der
0 1187: SEQUENCE
4 1: INTEGER 0
7 257: INTEGER
: 00 9A 40 FE 93 09 5B B2 6B F2 51 83 81 B9 59 32
: 58 3C 81 37 11 90 34 9A CA 51 9B BD ED 9F A1 04
: 6D CE 03 CE 5F 63 AA 15 09 DC A8 4F E2 83 9A D0
: 05 81 38 18 EF A2 91 90 75 58 40 7D C7 60 5A 5E
: 73 9B CD A6 D2 C9 35 DE 8E 54 90 97 47 A3 45 51
: 1D 9B ED A1 CB 92 B7 AC AB 23 CC AC 01 CD 53 5E
: B0 A7 CE 6A 74 70 0B 35 DE F6 12 85 0F 91 52 2D
: 1E A6 81 3A 57 71 EC 9F 6F C9 41 77 6E 90 16 AB
: [ Another 129 bytes skipped ]
268 3: INTEGER 65537
273 256: INTEGER
: 5B 26 C3 08 92 44 1C 68 0B 76 3D B6 BF 97 44 D7
: BD 51 42 00 5F ED A5 F6 9E 48 E0 EF F5 1F 4A 25
: B4 D2 AC F5 D3 48 23 4C 83 96 F6 35 CD 3D 03 65
: ED 58 FF EB 43 6E AF 25 98 73 EB 9F 90 81 76 44
: EC B1 96 BE 02 66 91 D0 1B 8A A1 CA 94 61 96 B0
: 5F 7F 09 D7 E9 28 1E A1 B6 F2 F0 45 D4 56 4A A3
: 2B 56 1F B4 14 AD 9B 34 D8 C6 52 D8 C3 30 03 37
: 94 7E D2 C1 EF B1 3A F9 EC BC 81 DD D4 C9 80 AB
: [ Another 128 bytes skipped ]
...
该程序是用 C++ 编写的,即使您有一个 C 标签。它允许我们避免大量的错误检查和清理,因为它是自动的。而且它很容易转换回 C。
#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 pem3(BIO_new_file("rsa-private-1.pem", "w"), ::BIO_free);
BIO_FILE_ptr pem4(BIO_new_file("rsa-private-2.pem", "w"), ::BIO_free);
BIO_FILE_ptr pem5(BIO_new_file("rsa-private-3.pem", "w"), ::BIO_free);
BIO_FILE_ptr der1(BIO_new_file("rsa-public.der", "w"), ::BIO_free);
BIO_FILE_ptr der2(BIO_new_file("rsa-private.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 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 public key in ASN.1/DER
rc = i2d_RSAPublicKey_bio(der1.get(), rsa.get());
ASSERT(rc == 1);
// Write public key in PKCS PEM
rc = PEM_write_bio_RSAPublicKey(pem1.get(), rsa.get());
ASSERT(rc == 1);
// Write public key in Traditional PEM
rc = PEM_write_bio_PUBKEY(pem2.get(), pkey.get());
ASSERT(rc == 1);
//////////
// Write private key in ASN.1/DER
rc = i2d_RSAPrivateKey_bio(der2.get(), rsa.get());
ASSERT(rc == 1);
// Write private key in PKCS PEM.
rc = PEM_write_bio_PrivateKey(pem3.get(), pkey.get(), NULL, NULL, 0, NULL, NULL);
ASSERT(rc == 1);
// Write private key in PKCS PEM
rc = PEM_write_bio_PKCS8PrivateKey(pem4.get(), pkey.get(), NULL, NULL, 0, NULL, NULL);
ASSERT(rc == 1);
// Write private key in Traditional PEM
rc = PEM_write_bio_RSAPrivateKey(pem5.get(), rsa.get(), NULL, NULL, 0, NULL, NULL);
ASSERT(rc == 1);
return 0;
【讨论】:
TIL,我不知道你可以用 unique_ptr 做到这一点。太酷了。 使用旧的RSA_generate_key()
时,需要调用RSA_check_key()
以确保密钥有效。 _ex 变体不需要这样做吗?【参考方案3】:
在使用 RAND_add
正确播种 PRNG 后,您将使用 RSA_generate_key_ex
。
编辑:
虽然最初编写此答案时需要调用 RAND_add
,但当前版本的 OpenSSL 不再需要手动播种 PRNG。
【讨论】:
Plus One 用于先致电RAND-add
。【参考方案4】:
kExp=3 可能是一个安全漏洞,请改用 65537。这个问题被称为“小 RSA 指数”,参见例如http://en.wikipedia.org/wiki/Coppersmith%27s_Attack 和 http://www.usna.edu/Users/math/wdj/book/node45.html 也请使用超过 1024 位。
【讨论】:
不是问题的答案。如果您正在尝试这样做,那么您最终将在另一个答案上获得足够的代表。 但是如果你把它放在 Fred 的回答之后会非常有用 这里也提到了:openssl.org/docs/crypto/RSA_generate_key.html以上是关于如何使用 OpenSSL 生成 RSA 私钥?的主要内容,如果未能解决你的问题,请参考以下文章