84

C / C ++アプリケーションがあり、公開鍵と秘密鍵の両方を含むX509pem証明書を作成する必要があります。証明書は自己署名することも、署名しないこともできます。

コマンドラインからではなく、アプリ内でこれを実行したいと思います。

どのOpenSSL関数がこれを実行しますか?サンプルコードはボーナスです!

4

4 に答える 4

213

これは非常に遅い(そして長い)答えであることを認識しています。しかし、この質問が検索エンジンの結果にどれだけランク付けされているかを考えると、まともな回答を書く価値があるかもしれないと思いました.

以下で説明する内容の多くは、このデモと OpenSSL ドキュメントから借用したものです。以下のコードは、C と C++ の両方に適用されます。


実際に証明書を作成する前に、秘密鍵を作成する必要があります。OpenSSL は、EVP_PKEYアルゴリズムに依存しない秘密鍵をメモリに格納するための構造を提供します。この構造体は in で宣言されてopenssl/evp.hいますが、by openssl/x509.h(後で必要になります) によってインクルードされているため、ヘッダーを明示的にインクルードする必要はありません。

EVP_PKEY構造体を割り当てるために、以下を使用しEVP_PKEY_newます。

EVP_PKEY * pkey;
pkey = EVP_PKEY_new();

構造体を解放するための対応する関数もあります - EVP_PKEY_free- 単一の引数を受け入れます:EVP_PKEY上記で初期化された構造体です。

次に、キーを生成する必要があります。この例では、RSA キーを生成します。これは、RSA_generate_keyで宣言されている関数で行われopenssl/rsa.hます。RSAこの関数は、構造体へのポインターを返します。

関数の単純な呼び出しは次のようになります。

RSA * rsa;
rsa = RSA_generate_key(
    2048,   /* number of bits for the key - 2048 is a sensible value */
    RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
    NULL,   /* callback - can be NULL if we aren't displaying progress */
    NULL    /* callback argument - not needed in this case */
);

の戻り値が の場合、RSA_generate_key何かNULL問題が発生しています。EVP_PKEYそうでない場合は、RSA キーを取得したので、それを以前の構造に割り当てることができます。

EVP_PKEY_assign_RSA(pkey, rsa);

構造体が解放されると、構造体はRSA自動的に解放EVP_PKEYされます。


次に、証明書自体について説明します。

OpenSSL はX509構造を使用して、メモリ内の x509 証明書を表します。この構造体の定義は にありopenssl/x509.hます。最初に必要になる関数はX509_new. その使用は比較的簡単です。

X509 * x509;
x509 = X509_new();

の場合と同様にEVP_PKEY、構造を解放するための対応する関数があります - X509_free

ここで、いくつかのX509_*関数を使用して、証明書のいくつかのプロパティを設定する必要があります。

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

これにより、証明書のシリアル番号が「1」に設定されます。一部のオープンソース HTTP サーバーは、デフォルトであるシリアル番号「0」の証明書の受け入れを拒否します。次のステップは、証明書が実際に有効である期間を指定することです。次の 2 つの関数呼び出しでそれを行います。

X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

最初の行は、証明書のnotBeforeプロパティを現在の時刻に設定します。(X509_gmtime_adj関数は指定された秒数を現在の時刻に追加します。この場合はなしです。) 2 行目は、証明書のnotAfterプロパティを今から 365 日 (60 秒 * 60 分 * 24 時間 * 365 日) に設定します。

ここで、以前に生成したキーを使用して、証明書の公開キーを設定する必要があります。

X509_set_pubkey(x509, pkey);

これは自己署名証明書であるため、発行者の名前をサブジェクトの名前に設定します。そのプロセスの最初のステップは、サブジェクト名を取得することです。

X509_NAME * name;
name = X509_get_subject_name(x509);

以前にコマンド ラインで自己署名証明書を作成したことがある場合は、国コードを求められたことを覚えているでしょう。ここでは、組織 ('O') および共通名 ('CN') と共に提供しています。

X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                           (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                           (unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                           (unsigned char *)"localhost", -1, -1, 0);

(私はカナダ人であり、それが国コードであるため、ここでは値「CA」を使用しています。また、パラメーター #4 を明示的に にキャストする必要があることに注意してくださいunsigned char *。)

これで、実際に発行者名を設定できます。

X509_set_issuer_name(x509, name);

最後に、署名プロセスを実行する準備が整いました。X509_sign以前に生成したキーで呼び出します。このためのコードは非常に単純です。

X509_sign(x509, pkey, EVP_sha1());

キーの署名にSHA-1ハッシュ アルゴリズムを使用していることに注意してください。mkcert.cこれは、この回答の冒頭で述べた、MD5 を使用するデモとは異なります。


これで自己署名証明書ができました!しかし、まだ終わっていません。これらのファイルをディスクに書き出す必要があります。ありがたいことに、OpenSSL では、PEM_*で宣言されている関数についても説明してくれましたopenssl/pem.h。最初に必要なのはPEM_write_PrivateKey、秘密鍵を保存するためのものです。

FILE * f;
f = fopen("key.pem", "wb");
PEM_write_PrivateKey(
    f,                  /* write the key to the file we've opened */
    pkey,               /* our key from earlier */
    EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
    "replace_me",       /* passphrase required for decrypting the key on disk */
    10,                 /* length of the passphrase string */
    NULL,               /* callback for requesting a password */
    NULL                /* data to pass to the callback */
);

秘密鍵を暗号化したくない場合は、NULL上記の 3 番目と 4 番目のパラメーターをそのまま渡します。いずれにせよ、ファイルが誰でも読み取り可能でないことを確実にする必要があります。(Unix ユーザーの場合、これは を意味しchmod 600 key.pemます。)

うわー!これで、関数は 1 つになりました。証明書をディスクに書き込む必要があります。これに必要な関数は次のPEM_write_X509とおりです。

FILE * f;
f = fopen("cert.pem", "wb");
PEM_write_X509(
    f,   /* write the certificate to the file we've opened */
    x509 /* our certificate */
);

これで完了です。この回答の情報で、すべてがどのように機能するかを大まかに理解するのに十分であると願っていますが、OpenSSL の表面をかじっただけではありません。

上記のすべてのコードが実際のアプリケーションでどのように見えるかを知りたい方のために、Gist (C++ で記述) をまとめました。ここで表示できます。

于 2013-02-26T05:51:05.687 に答える
51

最初に、用語とメカニズムに精通する必要があります。

X.509証明書には、定義上、秘密鍵は含まれていません。代わりに、公開鍵のCA署名バージョンです(CAが署名に入れる属性とともに)。PEM形式は、実際にはキーと証明書の個別のストレージのみをサポートしますが、2つを連結することもできます。

いずれの場合も、OpenSSL APIの20以上の異なる関数を呼び出して、キーと自己署名証明書を作成する必要があります。例は、Demos / x509/mkcert.cのOpenSSLソース自体にあります。

より詳細な回答については、以下のNathanOsmanの説明を参照してください。

于 2008-11-02T06:51:35.463 に答える
2

systemアプリ内からの呼び出しを介してこれを行う可能性はありますか? これを行ういくつかの正当な理由:

  • ライセンス:openssl実行可能ファイルを呼び出すと、ほぼ間違いなくアプリケーションから分離され、特定の利点が得られる場合があります。 免責事項:これについては弁護士に相談してください。

  • ドキュメント: OpenSSL には、潜在的に複雑なツールを大幅に簡素化する驚異的なコマンドライン ドキュメントが付属しています。

  • テスト容易性: 証明書の作成方法を正確に理解するまで、コマンド ラインから OpenSSL を実行できます。多くのオプションがあります。すべての詳細を正しく理解するまで、これに約 1 日を費やすことを期待してください。その後、コマンドをアプリに組み込むのは簡単です。

API の使用を選択した場合は、openssl-devwww.openssl.org の開発者リストを確認してください。

幸運を!

于 2008-11-02T02:44:17.693 に答える