Featured image of post ハッシュ・MAC・デジタル署名・証明書・鍵交換の関係

ハッシュ・MAC・デジタル署名・証明書・鍵交換の関係

目次

背景

昔、仕事で暗号技術を理解して実装する必要があった。

そのときに調べていたメモが見つかったため、消すのももったいないので、ここに整理して残しておく。今は細かいところを忘れているし、また必要になる時が来る気がする。

この記事では、暗号技術のうち、特に混乱しやすい以下の関係を整理する。

  • ハッシュ
  • MAC / HMAC
  • デジタル署名
  • デジタル証明書
  • PKI
  • 共通鍵暗号
  • 公開鍵暗号
  • Diffie-Hellman鍵交換
  • ゼロ知識証明

この記事の結論

暗号技術は、それぞれ守る対象が違う。

技術主な目的守れるもの守れないもの
共通鍵暗号暗号化機密性鍵配送、送信者の証明
ハッシュ要約値の生成変更検知の材料機密性、真正性
MAC / HMACメッセージ認証完全性、共有鍵ベースの真正性否認防止
デジタル署名署名・検証完全性、公開鍵ベースの真正性、否認防止機密性
デジタル証明書公開鍵の身元確認公開鍵と主体者の対応関係メッセージ本文の暗号化
DH / ECDH鍵交換鍵合意通信路に共有鍵を流さずに鍵材料を作ること相手認証単体

ざっくり言うと、こういう関係になる。

  1. メッセージを隠したいなら、AESなどの共通鍵暗号で暗号化する。
  2. メッセージが変わっていないか確認したいなら、ハッシュを使う。ただし、ハッシュだけでは攻撃者による改ざんには弱い。
  3. メッセージの改ざんと、共有鍵を知っている相手から来たことを確認したいなら、MACを使う。
  4. 第三者にも「この人が署名した」と示したいなら、デジタル署名を使う。
  5. その公開鍵が本当に本人のものか確認したいなら、デジタル証明書とPKIを使う。
  6. 通信のたびに安全な共通鍵を作りたいなら、DH / ECDH鍵交換を使う。

情報セキュリティ

情報セキュリティの三要素

情報セキュリティでは、よく次の3要素が使われる。

要素英語意味
機密性Confidentiality許可された者だけが情報にアクセスできる状態
完全性Integrity情報が正確で、改ざん・破壊されていない状態
可用性Availability許可された者が、必要なときに情報へアクセスできる状態

暗号技術は、このうち主に機密性・完全性・真正性を支えるために使われる。

ISMS

ISMSは Information Security Management System の略で、日本語では「情報セキュリティマネジメントシステム」と呼ばれる。

組織が情報の機密性・完全性・可用性を維持し、継続的に改善するための管理の仕組みである。

ZKP

ZKPとは

ZKPは Zero-Knowledge Proof の略で、日本語ではゼロ知識証明と呼ばれる。

ゼロ知識証明とは、証明者が「ある秘密を知っている」という主張を、秘密そのものを明かさずに検証者へ納得させるためのプロトコルである。

ポイントは次の通り。

  • 証明者は秘密を知っている
  • 検証者は秘密そのものを知らない
  • 検証者は「証明者が秘密を知っている」という事実だけを確認する
  • 秘密に関する余計な情報は漏れない

アリババの洞窟

前提

  • 洞窟にはAとBの2つの通路がある
  • 奥には鍵で開く扉があり、AとBは奥でつながっている
  • Victorは鍵を知らない
  • Peggyは鍵を知っている
  • Victorは、Peggyが本当に鍵を持っているか確認したい
  • Peggyは、Victorに鍵そのものを教えたくない

ここで妥協点として、Peggyは「扉を開ける能力がある」という事実だけを示す。鍵そのものは教えない。

アルゴリズム

初期状態では、Peggyは分岐点にいる。Victorは洞窟の入口にいる。

次のラウンドを必要な回数だけ繰り返す。

  1. Peggyは、分岐点からPath AまたはPath Bのどちらかを選んで進む。この時点でVictorはPeggyがどちらを選んだか見えない。
  2. Victorは、Peggyに「Aから戻ってきて」または「Bから戻ってきて」と指示する。
  3. Peggyは、Victorの指示通りのPathから分岐点に戻る。
    • Peggyが最初に選んだPathとVictorの要求Pathが同じなら、そのまま戻ればよい。
    • Peggyが最初に選んだPathとVictorの要求Pathが違うなら、扉の鍵を使って反対側へ移動し、要求されたPathから戻る。
  4. Victorは、Peggyが要求通りのPathから戻ってきたか確認する。
    • 要求通りなら検証OK。
    • 要求通りでなければ検証NG。「Peggyは鍵を持っていない」と判断する。
  5. Victorは入口に戻る。

Peggyが鍵を知らない場合、1回のラウンドを偶然突破できる確率は1/2である。ラウンド数を増やすほど、偶然すべて成功する確率は小さくなる。

注意点

重要なのは、PeggyがVictorの指示より前にPathを選択する点である。

Victorが先にPathを指定してしまうと、PeggyはそのPathに進めばよいだけになる。これでは、Peggyが鍵を持っていることの証明にならない。

また、VictorがPeggyの進んだPathを最初から見てしまうのもよくない。Victorに見られたという事実がPeggyへのヒントになり、プロトコルの性質が変わる。

OAuthとの違い

OAuthは、パスワードを第三者サービスに渡さずに権限を委譲する仕組みである。この点だけを見ると、「秘密を直接渡さない」という意味でゼロ知識証明と似て見える。

ただし、OAuthはゼロ知識証明ではない。OAuthは認可のためのフレームワークであり、第三者アプリケーションに限定的なアクセス権を与えるための仕組みである。

暗号の種類

共通鍵暗号と公開鍵暗号

暗号方式は、大きく次の2つに分けられる。

種類別名鍵の使い方代表例
共通鍵暗号対称鍵暗号、秘密鍵暗号暗号化と復号に同じ鍵を使うAES、ChaCha20
公開鍵暗号非対称鍵暗号公開鍵と秘密鍵のペアを使うRSA、ElGamal、楕円曲線暗号

共通鍵暗号

共通鍵暗号は、暗号化と復号に同じ鍵を使う方式である。

image.png

たとえばAESでは、送信者と受信者が同じ秘密鍵を共有し、その鍵でデータを暗号化・復号する。

共通鍵暗号の特徴は次の通り。

  • 処理が速い
  • 大量データの暗号化に向いている
  • 送信者と受信者が同じ鍵を持つ必要がある
  • 鍵をどう安全に共有するか、という鍵配送問題がある

代表的な共通鍵暗号には、AESやChaCha20がある。RC4、DES、3DESは歴史的には重要だが、現在の新規設計では避けるべきレガシーな方式として扱う方がよい。

公開鍵暗号

公開鍵暗号は、ペアとなる2つの鍵を使う方式である。

image.png

  • 公開鍵は他人に渡してよい
  • 秘密鍵は本人だけが持つ
  • 公開鍵で暗号化したデータは、対応する秘密鍵で復号する
  • 秘密鍵で作った署名は、対応する公開鍵で検証する

公開鍵暗号を使うと、共通鍵暗号のように「同じ鍵を事前に安全な経路で渡す」必要は減る。

ただし、公開鍵暗号にも別の問題がある。受け取った公開鍵が本当に相手本人のものか分からなければ、中間者攻撃を受ける可能性がある。そのため、公開鍵の真正性を確認する仕組みとして、デジタル証明書やPKIが必要になる。

Diffie-Hellman鍵交換

Diffie-Hellman鍵交換は、安全でない通信路上で、共通鍵の材料となる共有秘密を作るための鍵合意方式である。

注意点として、DH鍵交換は「共通鍵を安全に送る方式」ではない。共通鍵そのものは通信路に流さない。双方が公開情報を交換し、それぞれの秘密情報と組み合わせて同じ共有秘密を計算する。

その共有秘密から、KDF(Key Derivation Function)を使って実際の暗号鍵を導出する。

DH鍵交換の特徴は次の通り。

  • 共通鍵そのものを通信路に流さない
  • データ本文の暗号化方式ではない
  • 鍵交換・鍵合意のための方式である
  • 認証なしのDHは中間者攻撃に弱い
  • 実際のプロトコルでは、証明書や署名などと組み合わせて相手認証を行う

楕円曲線を使う方式はECDHと呼ばれる。現在のTLSでは、ECDHEのような一時鍵を使う方式がよく使われる。

ハッシュ

ハッシュ化とは

ハッシュ化とは、元データからハッシュ関数を使って固定長の値を生成する処理である。この固定長の値を、ハッシュ値、ダイジェスト、メッセージダイジェストなどと呼ぶ。

image.png

暗号学的ハッシュ関数には、主に次の性質が求められる。

性質意味
原像計算困難性ハッシュ値から元データを求めるのが困難であること
第二原像計算困難性あるデータと同じハッシュ値になる別データを作るのが困難であること
衝突困難性同じハッシュ値になる2つの異なるデータを見つけるのが困難であること

ハッシュは暗号化ではない。ハッシュ値から元データを復元することを目的としない。

ハッシュで確認できること

ハッシュは、データが変化していないか確認する材料として使える。

たとえば、ソフトウェアの配布元がハッシュ値を公開している場合、ダウンロードしたファイルのハッシュ値を自分で計算し、公開値と一致するか確認できる。

ただし、ハッシュだけで改ざんを防げるわけではない。攻撃者がファイル本体とハッシュ値の両方を差し替えられる場合、ハッシュ値も一緒に作り直されてしまう。

つまり、ハッシュ単体では次のことは保証できない。

  • 誰が作ったデータか
  • 攻撃者が本文とハッシュ値を両方差し替えていないか
  • データが秘匿されているか

これらを確認するには、MACやデジタル署名が必要になる。

代表的なハッシュ関数

代表的な暗号学的ハッシュ関数には、次のようなものがある。

  • SHA-256
  • SHA-384
  • SHA-512
  • SHA-3

MD5やSHA-1も歴史的にはよく使われたが、現在の新規設計では使うべきではない。MD5やSHA-1は衝突攻撃に対して弱く、現代のセキュリティ用途ではレガシーな方式として扱う。

CRC、チェックサム、パリティチェックとの違い

CRC、チェックサム、パリティチェックも、データの誤り検出に使われる。

ただし、これらは主に偶発的なエラー検出のための仕組みであり、攻撃者による意図的な改ざんに耐えることを目的としていない。

方式主な用途暗号学的な改ざん耐性
パリティチェック単純なビット誤り検出ない
チェックサム簡易な誤り検出ない
CRC通信・保存時の誤り検出ない
暗号学的ハッシュ改ざん検出の材料ある

パスワードのハッシュ化

通常のハッシュとの違い

パスワード保存では、単純にSHA-256などでハッシュ化するだけでは不十分である。

理由は、パスワードは人間が覚えるため、入力の候補が偏りやすいからである。攻撃者はよく使われるパスワードを大量に試すことで、ハッシュ値から元のパスワードを推測できる。

そのため、パスワード保存では専用のパスワードハッシュ方式を使う。

代表例は次の通り。

  • Argon2id
  • bcrypt
  • scrypt
  • PBKDF2

ソルト

ソルトは、パスワードごとに付与するランダムな値である。

パスワードとソルトを組み合わせてハッシュ化し、ソルトとハッシュ値をデータベースに保存する。

ソルトの目的は、同じパスワードでもユーザーごとに異なるハッシュ値にすること。これにより、レインボーテーブル攻撃や、同じパスワードを使っているユーザーの一括特定を難しくできる。

ソルトは秘密にする必要はない。ハッシュ値と一緒に保存してOK。

ストレッチング

ストレッチングは、ハッシュ計算を意図的に重くする考え方である。

攻撃者が1つの候補パスワードを試すたびに高い計算コストがかかるようにし、総当たり攻撃や辞書攻撃を遅くする。

現在は「数千〜数万回ハッシュ化する」とだけ考えるより、Argon2id、bcrypt、scrypt、PBKDF2などのパスワード保存用アルゴリズムを使い、ワークファクターやメモリコストを適切に設定する方がよい。

認証・真正性・完全性

用語の整理

用語意味
完全性データが改ざん・破壊されていないこと
真正性主張された主体・データ・記録が本物であること
認証相手やデータが主張通りであることを確認すること
否認防止後から「自分はやっていない」と否認しにくくすること

メッセージ認証とは、受信したメッセージが改ざんされておらず、期待した相手から来たものだと確認する技術である。

MAC / HMAC

MACとは

MACは Message Authentication Code の略で、日本語ではメッセージ認証コードと呼ばれる。

MACは、共有鍵とメッセージから短い認証コードを生成する仕組みである。

送信側は、メッセージと共有鍵からMAC値を計算し、メッセージと一緒に送る。受信側も同じ共有鍵と受信メッセージからMAC値を計算し、送られてきたMAC値と比較する。

一致すれば、次のことを確認できる。

  • メッセージが改ざんされていないこと
  • 同じ共有鍵を知っている相手がMAC値を作ったこと

image.png

HMACとは

HMACは、ハッシュ関数を使ってMACを構成する方式である。

たとえば、HMAC-SHA-256、HMAC-SHA-512などがある。

HMACは単なる hash(key + message) ではない。鍵とメッセージを安全に組み合わせるための決まった構造を持つ。

MACの限界

MACは、共有鍵を持つ者同士のメッセージ認証には向いている。

ただし、共有鍵を使うため、第三者に対する証明には向かない。AとBが同じ鍵を持っている場合、あるMAC値を作ったのがAなのかBなのかを第三者に証明できない。

そのため、MACには否認防止性がない。

AEAD

実際の通信では、「暗号化」と「MAC」を別々に組み合わせるより、AEADを使うことが多い。

AEADは Authenticated Encryption with Associated Data の略で、暗号化と認証をまとめて扱う方式である。

代表例は次の通り。

  • AES-GCM
  • ChaCha20-Poly1305

AEADを使うと、次の性質を同時に得られる。

  • メッセージの機密性
  • メッセージの完全性
  • メッセージの真正性
  • 追加認証データの保護

TLSなどの現代的なプロトコルでは、AEADが重要な役割を持つ。

デジタル署名

デジタル署名とは

デジタル署名は、秘密鍵で署名を生成し、公開鍵で署名を検証する仕組みである。

image.png

基本的な流れは次の通り。

  1. 送信者はメッセージを作成する。
  2. 送信者はメッセージからハッシュ値を計算する。
  3. 送信者は秘密鍵を使って署名値を生成する。
  4. 送信者はメッセージと署名値を受信者に送る。
  5. 受信者はメッセージからハッシュ値を計算する。
  6. 受信者は送信者の公開鍵を使って署名を検証する。
  7. 検証に成功すれば、メッセージの完全性と、秘密鍵を持つ主体による署名であることを確認できる。

ここで重要なのは、「秘密鍵で暗号化して公開鍵で復号する」と雑に理解しないこと。

RSA署名ではそのように説明されることもあるが、ECDSAやEdDSAではその説明は成り立たない。一般化して言うなら、秘密鍵で署名を生成し、公開鍵で署名を検証する、という理解がよい。

デジタル署名で分かること

デジタル署名によって、次のことを確認できる。

  • メッセージが改ざんされていないこと
  • 対応する秘密鍵を持つ主体が署名したこと
  • 署名者が後から否認しにくいこと

ただし、デジタル署名は暗号化ではない。署名付きメッセージは、暗号化されていなければ中身を読める。

機密性が必要なら、署名とは別に暗号化が必要である。

デジタル署名の代表例

代表的なデジタル署名方式には、次のものがある。

  • RSA署名
  • DSA
  • ECDSA
  • EdDSA

新規設計では、利用環境や標準に応じて、ECDSAやEdDSAなどの楕円曲線ベースの署名方式が使われることが多い。

MACとデジタル署名の違い

MACとデジタル署名は、どちらもメッセージの完全性と真正性に関係する。ただし、使う鍵と性質が違う。

比較項目MACデジタル署名
共通鍵秘密鍵・公開鍵ペア
検証者同じ共通鍵を持つ者公開鍵を持つ者
完全性確認できる確認できる
真正性共有鍵を知る相手として確認できる秘密鍵を持つ署名者として確認できる
否認防止できないできる
処理速度速いMACより重いことが多い
代表例HMAC-SHA-256、AES-CMACRSA署名、ECDSA、EdDSA

MACは「内輪での確認」に強い。デジタル署名は「第三者にも示せる証明」に強い。

PKIとデジタル証明書

PKIとは

PKIは Public Key Infrastructure の略で、日本語では公開鍵基盤と呼ばれる。

PKIの目的は、公開鍵と主体者の対応関係を信頼できる形で扱うこと。

公開鍵暗号やデジタル署名では、公開鍵を使って暗号化や検証を行う。しかし、そもそもその公開鍵が本当に相手本人のものか分からなければ意味がない。

そこで、CA(認証局)が「この公開鍵はこの主体者のものだ」と証明する。

image.png

デジタル証明書とは

デジタル証明書は、公開鍵と主体者情報を結びつけ、それにCAが署名したデータである。

より正確には、一般に使われるX.509証明書には、次のような情報が含まれる。

  • 主体者名
  • 主体者の公開鍵
  • 発行者名
  • 有効期間
  • 鍵用途
  • 拡張領域
  • CAによる署名

つまり、デジタル証明書は「公開鍵そのもの」ではない。「公開鍵が誰のものか」を証明するためのデータである。

デジタル署名とデジタル証明書の違い

用語たとえ役割
デジタル署名ハンコデータに対して、秘密鍵で署名する
デジタル証明書身分証・印鑑証明公開鍵が誰のものかをCAが証明する

デジタル署名は、メッセージやファイルなどのデータに対する署名である。

デジタル証明書は、公開鍵と主体者の対応関係に対する証明である。

ざっくり言うと、次の関係になる。

1
2
デジタル署名 = データに対して秘密鍵で作る署名
デジタル証明書 = 公開鍵と主体者情報に対してCAが署名したもの

証明書だけでは中身は隠れない

証明書は、公開鍵が誰のものかを確認するためのものだ。メッセージ本文を暗号化するものではない。

そのため、通信では次のように複数の技術を組み合わせる。

  1. 証明書で相手の公開鍵を確認する。
  2. 署名や証明書チェーンで相手を認証する。
  3. DH / ECDHで共有秘密を作る。
  4. KDFで共通鍵を導出する。
  5. AES-GCMやChaCha20-Poly1305などのAEADで通信内容を保護する。

属性証明書

通常のX.509公開鍵証明書は、公開鍵と主体者の対応関係を証明する。

一方、属性証明書は、主体者の権限や役割などの属性情報を証明するための証明書である。

たとえば、「この利用者は管理者権限を持つ」「この主体は特定のロールに所属する」といった情報を、公開鍵証明書とは別に扱う考え方である。

公開鍵証明書が「この公開鍵は誰のものか」を扱うのに対して、属性証明書は「その主体がどの属性を持つか」を扱う。

否認防止

デジタル署名には否認防止の効果がある。

たとえば、A社がB社へ発注書を送る場面を考える。A社が発注書にデジタル署名し、B社がA社の公開鍵で署名を検証できたとする。

このとき、B社は次のことを主張しやすくなる。

  • 発注書は改ざんされていない
  • A社の秘密鍵で署名された
  • A社は後から「送っていない」と否認しにくい

ただし、現実の否認防止は署名アルゴリズムだけでは完結しない。秘密鍵の管理、証明書の有効性、失効確認、タイムスタンプ、運用ルールなども関係する。

全体の流れ

ここまでの話を、実際の通信に近い流れでまとめる。

  1. 暗号化で機密性を守る
    • メッセージを第三者に見られたくない場合、AESなどの共通鍵暗号で暗号化する。
    • ただし、暗号化だけでは「改ざんされていないか」「誰が送ったのか」までは十分に確認できない。
  2. ハッシュで変更検知の材料を作る
    • ハッシュを使うと、データから固定長の値を作れる。
    • ハッシュ値を信頼できる経路で受け取れるなら、データが変化していないか確認できる。
    • ただし、攻撃者が本文とハッシュ値を両方差し替えられる場合、ハッシュだけでは不十分である。
  3. MACでメッセージ認証する
    • 共有鍵を使ってMACを計算すれば、メッセージの完全性と、共有鍵を知っている相手から来たことを確認できる。
    • ただし、MACは共有鍵方式であるため、第三者に対する否認防止には使いにくい。
  4. デジタル署名で第三者にも示せる署名を作る
    • デジタル署名を使えば、秘密鍵で署名を生成し、公開鍵で検証できる。
    • これにより、完全性、公開鍵ベースの真正性、否認防止を実現できる。
    • ただし、デジタル署名だけでは本文は隠れない。
  5. 証明書で公開鍵を信頼する
    • デジタル署名を検証するには公開鍵が必要である。
    • しかし、その公開鍵が本当に本人のものか分からなければ、検証結果は信用できない。
    • そこで、CAが署名したデジタル証明書を使い、公開鍵と主体者の対応関係を確認する。
  6. 鍵交換で通信ごとの共通鍵を作る
  • 共通鍵暗号は高速だが、共通鍵をどう共有するかという問題がある。
  • DH / ECDH鍵交換を使うと、共通鍵そのものを通信路に流さずに、双方で共有秘密を作れる。
  • 実際の通信では、公開鍵証明書で相手を認証し、ECDHEなどで共有秘密を作り、そこから導出した共通鍵でAEAD暗号化する、というハイブリッド方式がよく使われる。

まとめ

暗号技術は、ひとつだけで全てを守るものではない。

  • 機密性を守るなら、共通鍵暗号やAEADを使う
  • 完全性の確認材料を作るなら、ハッシュを使う
  • 共有鍵ベースで真正性も確認するなら、MACを使う
  • 第三者にも示せる署名が必要なら、デジタル署名を使う
  • 公開鍵の持ち主を確認するなら、デジタル証明書とPKIを使う
  • 通信ごとの鍵を安全に作るなら、DH / ECDH鍵交換を使う

ハッシュ、MAC、デジタル署名、証明書は似た場所に出てくるため混乱しやすい。

しかし、見るべき軸はシンプル。

観点使う技術
中身を隠したい暗号化、AEAD
変わっていないか見たいハッシュ、MAC、署名
共有鍵を知る相手か見たいMAC
秘密鍵を持つ署名者か見たいデジタル署名
公開鍵が本人のものか見たいデジタル証明書、PKI
共通鍵を通信ごとに作りたいDH / ECDH鍵交換

この対応関係を押さえると、暗号技術の全体像がかなり見えやすくなる。

そのうち、エンドツーエンドの暗号化やmTSLや秘密分散なども残す。

参考文献

Built with Hugo
テーマ StackJimmy によって設計されています。