web-dev-qa-db-ja.com

OpenSSLを使用してRSA秘密鍵を生成する方法は?

CソースファイルでOpenSSLライブラリを使用してRSA秘密鍵を生成する方法を知りたい。端末コマンドを使用して生成する方法を知っています。

実際、私のserver.cファイルは秘密鍵を生成してclient.cに送信します。可能であれば、ソースコードを教えてください。

Linuxマシンで作業しています。

24
Usman
#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);
33
Fred

Cソースファイルのopensslライブラリを使用してRSA秘密鍵を生成する方法を知りたいですか?

キーの生成は簡単です。 RSA_generate_key_ex。以下のプログラムは、その方法を示しています。

形式を知る必要があるため、公開鍵と秘密鍵の保存は別の問題です。以下のプログラムは、いくつかの形式でそれを行う方法を示しています。


さまざまな関数とフォーマットを以下に示します。

関連、 「BEGIN RSA PRIVATE KEY」と「BEGIN PRIVATE KEY」の違いは何ですか を参照してください。 SubjectPublicKeyInfoPrivateKeyInfo、および公開鍵と秘密鍵の違いについて説明します。

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;
}
25
jww

PRNG RSA_generate_key_ex を使用して適切にシードした後、 Rand_add を使用します。

編集:この回答が最初に書かれたときにRand_addを呼び出す必要がありましたが、OpenSSLの現在のバージョンでは、PRNGを手動でシードする必要がなくなりました。

8
Hasturkun

kExp = 3はセキュリティホールになる可能性があります。代わりに65537を使用してください。この問題は「小さなRSA指数」と呼ばれます。 http://en.wikipedia.org/wiki/Coppersmith%27s_Attack および http://www.usna.edu/Users/math/wdj/book/node45.html =また、1024ビット以上を使用してください。

7