blog

技術|OpenSSLの使い方:ハッシュ、デジタル署名、その他!

ハッシュ、デジタル署名、デジタル証明書などなど。...

Oct 28, 2025 · 14 min. read
シェア

ハッシュ、デジタル署名、デジタル証明書など、OpenSSLを使った暗号技術の詳細に飛び込みましょう。

ハッシュ化、暗号化/復号化、デジタル署名、デジタル証明書については、OpenSSLライブラリとコマンドラインユーティリティを通じて紹介します。ここでは、その詳細をより深く掘り下げていきます。まず、コンピューティングではどこにでもあるハッシュから始め、ハッシュ関数を構成するものについて考えてみましょう。

暗号ハッシュ

ハッシュ値はコンピューティングの多くの分野で使用されています。例えば、ビットコインのブロックチェーンはブロック識別子としてSHA256ハッシュを使用しています。ビットコインを採掘するには、指定されたしきい値以下のSHA256ハッシュを生成する必要があります。興味深い点として、今日のマイナーは、SHA256 ハッシュを並行して生成するように設計されたハードウェアのクラスタです。2018年のピーク時には、世界中のビットコインマイナーが毎秒約7500万を生成していました。

つまり、受信したメッセージが送信したメッセージと同じであることを保証するためです。メッセージ送信者はメッセージのチェックサムを計算し、その結果をメッセージと一緒に送信します。メッセージが到着すると、受信者はチェックサムを再計算します。送信されたチェックサムが再計算されたチェックサムと一致しない場合、送信中のメッセージか、送信されたチェックサムか、あるいはその両方に何か問題があった可能性があります。この場合、メッセージとそのチェックサムを再送するか、少なくともエラー状態を発生させなければなりません。

ハッシュ化の例は他にもあります。例えば、ユーザがパスワードで認証する必要があるウェブサイトでは、ユーザはブラウザにパスワードを入力し、次にHTTPSでサーバに接続し、パスワードはブラウザから暗号化されてサーバに送信されます。パスワードがサーバに届くと、復号化され、データベースのテーブル検索が実行されます。

このルックアップテーブルには何を格納すべきでしょうか?パスワードそのものを保存するのは危険です。もっとリスクの少ない方法は、パスワードから生成されたハッシュ値を保存することで、おそらくハッシュ値の計算に「改良の趣向を加える」ことでしょう。パスワードはウェブサーバーに送信されるかもしれませんが、サイト側はそこに保存されないことを保証できます。

ハッシュ値はセキュリティの様々な分野でも登場します。例えば、) はハッシュ値とシークレットを使用して、ネットワーク経由で送信されるメッセージを認証します。HMAC コードは軽量でプログラムでの使用が容易であり、Web サービスでよく使用されています。X509デジタル証明書はハッシュと呼ばれるハッシュ値で構成され、証明書の検証を容易にします。メモリ内のものはこのようなフィンガープリントをキーとするルックアップテーブルとして、つまり一定のルックアップ時間をサポートするものとして実装することができます。入ってくる証明書からのフィンガープリントは信頼されたストレージの鍵と比較され、一致するかどうか判断されます。

  1. foobar >|chf| >hash value ## シンプルでわかりやすい

一方、その逆は不可能です:

  1. +-----------+
  2. hash value >|chf inverse| >foobar ## トリッキーな難題
  3. +-----------+

例えば、SHA256ハッシュ関数を思い出してください。任意の長さN > 0の入力ビット列に対して、この関数は256ビットの固定長ハッシュを生成します。したがって、ハッシュは文字列の各ビットの値はおろか、入力ビット列の長さNさえも反映しません。ちなみに、SHA256の対象化は簡単ではありません。SHA256ハッシュをリバースエンジニアリングする唯一の効果的な方法は、計算されたSHA256ハッシュをブルートフォースサーチによって入力ビット列に戻すことです。このような検索は、SHA256のような確立された暗号ハッシュ関数では実行不可能です。

さて、最後におさらいしておくべき知識はこれです。暗号ハッシュは統計的に一意であり、無条件に一意というわけではありません。HMAC、直感に反する衝突の良い例です。様々なハッシュアルゴリズムに関する広範な研究が行われてきました。例えば、MD5の衝突耐性は2ハッシュ程度で壊れます。SHA1では、約2ハッシュで壊れ始めます。

SHA256の衝突耐性のプロファイリングについては、良い見積もりはありません。SHA256には2つの異なるハッシュ値の範囲があり、この数値の10進数表現は78ビットもあります!では、SHA256ハッシュは衝突する可能性があるのでしょうか?もちろん、可能性は低いです。

以下のコマンドラインの例では、ビット文字列ソースとして2つの入力ファイルhashIn1.txtとhashIn2.txtが使用されています。 1つ目のファイルにはabcが、2つ目のファイルには1a2b3cが含まれています。

読みやすくするために、これらのファイルにはテキストが含まれていますが、代わりにバイナリファイルを使用することもできます。

Linuxのsha256sumユーティリティをコマンドラインで使用して、これらの2つのファイルを処理すると、以下のハッシュが生成されます。

  1. % sha256sum hashIn1.txt
  2. 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dcafb hashIn1.txt
  3. % sha256sum hashIn2.txt
  4. 3eaacbf4e8840dd4c2e5906ed13 hashIn2.txt

OpenSSLのハッシュは期待通りです:

  1. % openssl dgst -sha256 hashIn1.txt
  2. SHA256(hashIn1.txt)= 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dcafb
  3. % openssl dgst -sha256 hashIn2.txt
  4. SHA256(hashIn2.txt)= 3eaacbf4e8840dd4c2e5906ed13

この暗号ハッシュ関数の研究は、デジタル署名とその鍵ペアとの関係をより詳しく見るための基礎となります。

デジタル署名

その名が示すように、文書やその他の電子的なものに添付して、その真正性を証明することができます。そのため、この署名は紙の文書に手書きで署名するのと似ています。デジタル署名を検証することは、2つのことを確認することです。1つ目は、文書の暗号化ハッシュの一部に基づいているため、証明される遺物が署名が添付されてから変更されていないこと。第二に、署名がある人物のものであり、その人物だけが鍵ペアの秘密鍵にアクセスできること。ところで、コードをデジタル署名することは、プログラマーの間では一般的になっています。

デジタル署名がどのように作成されるかを理解しましょう。前述したように、公開鍵と秘密鍵のペアがなければ電子署名は成り立ちません。OpenSSLを使用してこれらの鍵を作成する場合、2つの別々のコマンドがあります。1つは秘密鍵を作成するコマンドで、もう1つは秘密鍵から一致する公開鍵を抽出するコマンドです。これらの鍵ペアはbase64でエンコードされ、この過程でサイズを指定できます。

は値で構成され、そのうちの2つが公開鍵を構成します。秘密鍵ファイルには秘密鍵が含まれていますが、抽出された公開鍵は対応する秘密鍵の値を明らかにしません

その結果、生成される秘密鍵ファイルには完全な鍵ペアが含まれることになります。2つの鍵は用途が異なるため、公開鍵を独自のファイルに抽出するのが現実的であり、 また、この抽出により、秘密鍵が誤って公開されるリスクを最小限に抑えることができます。

次に、鍵ペアの秘密鍵を使用して対象アーティファクトのハッシュを生成し、署名を作成します。もう一方の受信側のシステムは、鍵ペアの公開鍵を使用してアーティファクトに添付された署名を検証します。

では、例を示します。まず、OpenSSLで2048ビットのRSAキー・ペアを生成します:

  1. openssl genpkey -out privkey.pem -algorithm rsa 4028

この例では、genpkeyはデフォルトでRSAタイプなので、-algorithm rsaフラグは四捨五入できます。ファイル名は任意ですが、拡張子.pemはデフォルトのPEM形式の通常の拡張子です。より大きな鍵サイズが必要な場合は、最後の引数を.これらのサイズは常に2の累乗です。

以下は、base64エンコードされた結果の privkey.pem ファイルのスニペットです:

  1. -----BEGIN PRIVATE KEY-----
  2. MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANnlAh4jSKgcNj / Z;
  3. JF4J4WdhkljP2R+TXVGuKVRtPkGAiLWE4BDbgsyKVLfs2EdjKL1U+/qtfhYsqhkK
  4. -----END PRIVATE KEY-----

次のコマンドは、秘密鍵からペアの公開鍵を抽出します:

  1. openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem

出来上がった pubkey.pem ファイルは十分に小さいので、ここでその全体をお見せすることができます:

  1. -----BEGIN PUBLIC KEY-----
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ5QIeI0ioHDY/2SReCeFnYZJY
  3. z9kfk11RrilUbT5BgIi1hOAQ24LMilS37NhHYyi9VPv6rX4WLKoZCmkeYaWk / TR5;
  4. 4nbH1E/AkniwRoXpeh5VncwWMuMsL5qPWGY8fuuTE27GhwqBiKQGBOmU+MYlZonO
  5. O0xnAKpAvysMy7G7qQIDAQAB
  6. -----END PUBLIC KEY-----

キー・ペアがあれば、デジタル署名は簡単です。この場合、ソース・ファイルclient.cが署名される成果物です:

  1. openssl dgst -sha256 -sign privkey.pem -out sign.sha256 client.c

client.cソースファイルのダイジェストはSHA256で、秘密鍵は先に作成したprivkey.pemファイルにあります。結果のバイナリ署名ファイルはsign.sha652で、これは任意の名前です。このファイルの読み取り可能なバージョンを取得するには、後続のコマンドを実行します:

  1. openssl enc -base64 -in sign.sha256 -out sign.sha256.base64

ファイル sign.sha256.base64 内容は以下の通りです:

  1. h+e+3UPx++KKSlWKIk34fQ1g91XKHOGFRmjc0ZHPEyyjP6/lJ05SfjpAJxAPm570
  2. VNfFwysvqRGmL0jkp / TTdwnDTwt756Ej4X3OwAVeYM7i5DCcjVsQf5 + h7JycHKlM;
  3. o/Jd3kUIWUkZ8+Lk0ZwzNzhKJu6LM5KWtL+MhJ2DpVc=

あるいは、実行可能クライアントが署名され、その結果得られるbase64エンコードされた署名は、予想通り異なるものになります:

  1. VMVImPgVLKHxVBapJ8DgLNJUKb98GbXgehRPD8o0ImADhLqlEKVy0HKRm/51m9IX
  2. xRAN7DoL4Q3uuVmWWi749Vampong / uT5qjgVNTnRt9jON112fzchgEoMb8CHNsCT;
  3. XIMdyaPtnJZdLALw6rwMM55MoLamSc6M/MV1OrJnk/g=

プロセスの最終段階は、公開鍵による電子署名の検証です。検証の重要なステップとして、成果物に署名するために使用されたハッシュ値を再計算する必要があります。

この目的で使用されるOpenSSLコマンドは2つあります。最初のコマンドは base64 署名をデコードします。

  1. openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha652

2つ目は署名の検証です:

  1. openssl dgst -sha256 -verify pubkey.pem -signature sign.sha256 client

2番目のコマンドの出力は、以下のようになるはずです:

  1. Verified OK

認証に失敗したときに何が起こるかを確認するために、短いけれども役に立つ練習は、最後のOpenSSLコマンドの実行可能なクライアント・ファイルをソース・ファイルclient.cに置き換えて、認証を試すことです。もうひとつの練習は、クライアント・プログラムを少し変えて、もう一度やってみることです。

デジタル証明書

ハッシュ、キー・ペア、デジタル署名、暗号化/復号化など、これまでに分析したさまざまなコンポーネントを統合したものです。プロダクション・グレードの証明書の最初のステップは、証明書を作成し、それを送信することです。OpenSSLの例でこれを行うには、以下を実行します:

  1. openssl req -out myserver.csr -new -newkey rsa:4096 -nodes -keyout myserverkey.pem

この例では、CSR 文書を生成し、その文書をファイル myserver.csr に格納します。ここでの目的は、CSR 文書が、指定されたドメイン名に関連する身元を保証することを CA に要求することです。

既存の鍵ペアを使用することもできますが、このコマンドは新しい鍵ペアも生成します。myserver.csrやmyserverkey.pemのような名前でのserverの使用は、電子証明書の典型的な用途を意味することに注意してください:www.google.comなどのドメイン名に関連付けられたWebサーバのID保証として。

しかし、このコマンドを使用すると、使用される電子証明書に関係なくCSRが再度作成されます。また、要求者の電子証明書にリンクされるドメイン名に関する関連情報の入力を求める質問/回答の対話型セッションが開始されます。この対話型セッションは、コマンドで基本情報を提供し、バックスラッシュで続けることで、1つのステップで完了できます。subjフラグは、必要な情報を提供します。

  1. % openssl req -new \
  2. -newkey rsa:2048 -nodes -keyout privkeyDC.pem \
  3. -out myserver.csr \
  4. -subj "/C=US/ST=Illinois/L=Chicago/O=Faulty Consulting/OU=IT=myserver.com"

生成されたCSRファイルはCAに送られ、チェックと検証を受けます。このプロセスにより、必要な形式、署名、有効期間などを持つデジタル証明書が作成されます。

  1. openssl req -text -in myserver.csr -noout -verify

以下は出力の一部です:

  1. verify OK
  2. Certificate Request:
  3. Version: 0 (0x0)
  4. Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT,=myserver.com
  5. Subject Public Key Info:
  6. Public Key Algorithm: rsaEncryption
  7. Public-Key: (2048 bit)
  8. Modulus:
  9. 00:ba:36:fb::bc::1b:6e:de:73:
  10. Exponent: x10001)
  11. Attributes:
  12. Signature Algorithm: sha256WithRSAEncryption

自己署名証明書

HTTPS ウェブサイトを開発する場合、CA プロセスを経る必要のないデジタル証明書を用意しておくと便利です。HTTPS ハンドシェイクの認証フェーズではこれで十分ですが、最近のブラウザーはこのような証明書は価値がないと警告します。この例を続けると、自己署名証明書用のOpenSSLコマンドは以下のようになります:

  1. openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout myserver.pem -out myserver.crt

以下のOpenSSLコマンドは、生成された証明書の可読バージョンを表示します:

  1. openssl x509 -in myserver.crt -text -noout

これは自己署名本の出力の一部です:

  1. Certificate:
  2. Version: 3 (0x2)
  3. Serial Number: (0xc5a9055a)
  4. Signature Algorithm: sha256WithRSAEncryption
  5. Issuer: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT,=myserver.com
  6. Validity
  7. Not Before: Apr : GMT
  8. Not After : Apr : GMT
  9. Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT,=myserver.com
  10. Subject Public Key Info:
  11. Public Key Algorithm: rsaEncryption
  12. Public-Key: (4096 bit)
  13. Modulus:
  14. 00:ba:36:fb::bc::1b:6e:de:73:
  15. Exponent: x10001)
  16. X509v3 extensions:
  17. X509v3 Subject Key Identifier:
  18. 3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
  19. X509v3 Authority Key Identifier:
  20. keyid:3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
  21. X509v3 Basic Constraints:
  22. CA:TRUE
  23. Signature Algorithm: sha256WithRSAEncryption
  24. 3a:eb:8d:b:5c:2e:48:ed:14:ce:f9:e:90:c9:

前述したように、RSA秘密鍵には公開鍵の生成に使われる値が含まれています。しかし、与えられた公開鍵が、それにマッチする秘密鍵を明らかにすることはありません。基礎となる数学理論については、 /_hmを参照。

電子証明書とその生成に使用された鍵ペアの間には、証明書が自己署名されたものであっても、重要な対応関係があります:

  • 電子証明書には、公開鍵を構成するインデックスとモジュラスの値が含まれています。これらの値は、最初に生成されたPEMファイル(この場合はファイル myserver.pemキー・ペアの一部です。
  • キー・ペアはデジタル証明書のモジュラスと一致する必要があります。

モジュラスは、読みやすくするためにハッシュ化できる大きな値です。以下は、同じモジュラスをチェックして、デジタル証明書がPEMファイル内のキー・ペアに基づいていることを確認する2つのOpenSSLコマンドです。

  1. % openssl x509 -noout -modulus -in myserver.crt | openssl sha1 ## 証明書におけるモジュラス
  2. (stdin)= eaa2c3a5d2e6739
  3. % openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## 鍵のモジュラス
  4. (stdin)= eaa2c3a5d2e6739

その結果、ハッシュが一致し、電子証明書が指定された鍵ペアに基づくことが確認されます。

キー配布に戻る

第 1 部の最後で提起された問題、すなわちクライアントアプリケーションと Google ウェブサーバの間の TLS ハンドシェイクに戻りましょう。クライアントアプリケーションと Google ウェブサーバとの間の TLS ハンドシェイクです。ハンドシェイクプロトコルには様々なものがあり、クライアントの例で使用した Diffie-Hellman のバージョンでさえ、異なるアプローチを持っています。それでも、クライアントの例は共通のパターンに従っています。

まず、TLSハンドシェイクの間に、クライアント・プログラムとウェブ・サーバーは、特に使用するアルゴリズムについて合意します。この例では、スイートは % openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## キーモッドです。

現在注目されている2つの要素は、RSAキー・ペア・アルゴリズムと、ハンドシェイクが成功した場合にメッセージを暗号化・復号化するためのAES128ブロック暗号です。暗号化/復号化に関しては、このプロセスに関して2つの流派があります。対称型では、暗号化と復号化には鍵を使います。鍵を両者に安全に配布するには?非対称型では、一方の鍵が暗号化に使われ、もう一方の鍵が復号化に使われます。

クライアント・プログラムは証明書を認証した Google ウェブ・サーバの公開鍵を持っており、ウェブ・サーバは同じペアの鍵から秘密鍵を持っています。その結果、クライアントプログラムはウェブサーバに暗号化されたメッセージを送信することができ、ウェブサーバはその通信を個別に復号化することができます。

TLSの場合、対称型アプローチには2つの大きな利点があります:

  • クライアント・プログラムとグーグル・ウェブ・サーバー間のやりとりでは、認証は一方向です。グーグル・ウェブ・サーバーは3つの証明書をクライアント・プログラムに送りますが、クライアント・プログラムはウェブ・サーバーに証明書を送らないため、ウェブ・サーバーはクライアントに送られるメッセージを暗号化するための公開鍵をクライアントから受け取ることができません。
  • AES128を使用した対称暗号化/復号化は、RSA鍵を使用した非対称暗号化/復号化よりも1000倍近く高速です。

TLSハンドシェイクは、2つの暗号化/復号化方式を巧みに組み合わせたものです。ハンドシェイクの間、クライアントプログラムはランダムビットを生成します。その後、クライアントプログラムは PMS をサーバの公開鍵で暗号化し、暗号化された PMS をサーバに送ります。サーバは PMS メッセージを RSA 鍵ペアの秘密鍵で復号化します:

  1. +-------------------+ encrypted PMS +--------------------+
  2. client PMS--->|serverの公開鍵|--------------->|serverの秘密鍵|--->server PMS
  3. +-------------------+ +--------------------+

このプロセスの最後に、クライアントプログラムと Google ウェブサーバは同じ PMS ビットを持つことになります。各当事者はこれらのビットを使って一つを生成し、すぐに対称暗号化/復号鍵と呼ばれるものを生成します。これで二つの異なる、しかし等価なセッション鍵が存在することになります。クライアントの場合、セッション鍵はAES128です。クライアント側と Google ウェブサーバ側の両方でセッション鍵が生成されると、 それぞれのセッション鍵はクライアントと Google ウェブサーバの間のやりとりを秘密にします。ハンドシェイクプロトコルでは、どちらか一方がハンドシェイクの再開を要求した場合、PMSプロセス全体を繰り返すことができます。

まとめ

コマンドラインで説明されている OpenSSL の操作は、基礎となるライブラリーの API を通して行うこともできます。この2つの記事では、例を短くし、暗号のトピックに焦点を当てるため、このユーティリティの使用に焦点を当てています。もしあなたがセキュリティーに興味があるなら、OpenSSL は良い出発点であり、掘り下げる価値があります。

経由

Read next

Hardcore Watch|Hardcore Watch #1228 研究者、ハリー・ポッターを使ってAIの「忘却」機能を研究する

🅷 研究者がハリー・ポッターを使ってAIの「忘却」能力を研究\n🄸 Windows 11はWindows Updateでシステムを修正可能に\n🄸 νρηを装った3つの悪質なChrome拡張機能が150万回ダウンロード\n"\n" "

Oct 28, 2025 · 3 min read