TL

暗号の基礎(共通鍵・公開鍵・ハッシュ・署名)

暗号は「隠す」だけの道具ではない。秘匿(共通鍵/公開鍵)・改ざん検知(ハッシュ)・本人保証(署名)という別目的の道具を、用途で正しく使い分けるのが要点。

基礎暗号公開鍵ハッシュ電子署名最終更新: 2026-06-04
TL;DR要点だけ先に
  • 1.暗号の道具は大きく4つ。共通鍵・公開鍵(隠す)、ハッシュ(指紋=改ざん検知)、電子署名(本人&改ざん防止)で、それぞれ目的が違う。
  • 2.共通鍵は速いが鍵の配り方が課題。公開鍵は遅いが鍵を安全に渡せる。だから実務は両者を組み合わせる(ハイブリッド)。
  • 3.「署名」は中身を隠さない。改ざん検知と本人確認のための仕組みで、秘匿が要るなら別途“暗号化”する――ここが一番の誤解ポイント。

そもそも何を守るのか

「暗号で守る」と一括りにされますが、守る対象は3つに分かれます。ここを混同すると「暗号化したのに安全じゃない」が起きます。

  • 機密性(Confidentiality):第三者に読まれない。盗聴対策。→ 暗号化(共通鍵・公開鍵)
  • 完全性(Integrity):途中で書き換えられていない。改ざん検知。→ ハッシュ・署名
  • 真正性(Authenticity)確かにその相手が作った。なりすまし防止。→ 電子署名・証明書
“暗号化=安全”ではない

暗号化が守るのは機密性だけです。暗号化された通信でも、相手が偽サーバなら(真正性なし)意味がなく、暗号文を途中で破壊・差し替えられても(完全性なし)気づけないことがあります。だから実システムは、暗号化に改ざん検知(ハッシュ/署名)と相手確認(証明書)をセットで使います。「隠す」と「改ざん防止」と「本人確認」は別の問題だと押さえてください。

共通鍵暗号(対称):速いが鍵配送が課題

暗号化と復号に同じ1本の鍵を使う方式です。送り手と受け手が同じ鍵を共有しておけば、その鍵で隠したり戻したりできます。仕組みが単純なぶん非常に高速で、大量データの暗号化に向きます(代表例は AES-GCM)。

弱点はただ一つ、**「その共通鍵をどうやって相手に安全に渡すか」**です。鍵そのものが盗まれたら全て解読されてしまうのに、鍵を送る経路がまだ暗号化されていない――という鶏と卵の問題(鍵配送問題)が生じます。

// 共通鍵暗号:同じ鍵で暗号化も復号もする(双方向)
const key = randomKey();                 // この1本を相手と「安全に」共有できるかが課題
const enc = encryptAES(plaintext, key);  // 暗号化
const dec = decryptAES(enc, key);        // 同じ鍵で復号 → 元に戻る

公開鍵暗号(非対称):鍵配送を解く代わりに遅い

鍵を**「公開鍵」と「秘密鍵」のペアにしたのが公開鍵暗号です。公開鍵で暗号化したものは、対になる秘密鍵でしか復号できません。公開鍵はその名のとおり誰に配ってもよい**ので、共通鍵暗号の弱点だった鍵配送問題を解けます。

  • 受け手は公開鍵を世界中に公開し、秘密鍵は自分だけが厳重に保管する。
  • 送り手は受け手の公開鍵で暗号化して送る。復号できるのは秘密鍵を持つ受け手だけ

ただし計算が重く、共通鍵に比べて桁違いに遅い。そのため大量データをそのまま公開鍵で暗号化することはせず、**「最初の鍵交換だけ」**に使うのが定石です(代表例は RSA / ECDH)。

実務は“ハイブリッド”:いいとこ取り

速い共通鍵と、鍵を安全に渡せる公開鍵を組み合わせるのが現実解です。「遅いが安全な公開鍵で“共通鍵そのもの”を安全に共有し、以降の大量データは速い共通鍵で暗号化する」。TLS のハンドシェイクはまさにこれで、最初だけ公開鍵方式で鍵を共有し、本データは共通鍵で流します。

両者は性質がほぼ対照的です。

観点共通鍵暗号(対称)公開鍵暗号(非対称)
1本の共通鍵を共有公開鍵+秘密鍵のペア
速度速い(大量データ向き)遅い(少量・鍵交換向き)
鍵配送鍵を安全に渡すのが難題公開鍵は配ってよい=渡しやすい
主な用途実データの暗号化鍵交換・電子署名
代表例AES-GCM / ChaCha20RSA / ECDH / ECDSA

ハッシュ:戻せない「データの指紋」

ハッシュ関数は、任意長のデータを固定長の短い値(ハッシュ値)に潰す一方向の関数です。暗号化と決定的に違うのは、元に戻せないこと。鍵もなく、ハッシュ値から元データを復元する手段はありません。

良いハッシュ関数(SHA-256 など)には次の性質があります。

  • 一方向性:ハッシュ値から元データを求められない。
  • 衝突困難性:違う入力が同じハッシュ値になるペアを、現実的に作れない。
  • 雪崩効果:入力が1ビット変わるだけで、出力が全く別物になる。
sha256("hello")  // → 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
sha256("hellp")  // → 一文字違うだけで全く別の値になる(雪崩効果)
// ハッシュ値から "hello" を逆算する方法は無い(一方向)

この「少しでも変われば指紋が変わる」性質から、ハッシュは**改ざん検知(完全性)**やファイルの同一性チェックに使われます。配布ファイルのチェックサム、Git のコミットID なども実体はハッシュです。

パスワード保存に“素のハッシュ”は使わない

パスワードの保存に SHA-256 などの汎用ハッシュをそのまま使うのは危険です。汎用ハッシュは高速なため、攻撃者が大量の候補を片端から試す総当たりや、事前計算したレインボーテーブルに弱い。パスワードには、利用者ごとに異なるソルトを足し、**わざと計算を遅くした専用関数(bcrypt / scrypt / Argon2)**を使うのが正解です。詳しくは パスワードの安全な保存 を参照。

電子署名:本人+改ざんを同時に保証

ここまでの「秘匿(暗号化)」とは目的が違います。電子署名が証明するのは、「確かにこの人が作った(真正性/なりすまし防止)」かつ「作られてから書き換えられていない(完全性/改ざん防止)」の2点です。中身を隠すものではないことに注意。

仕組みは公開鍵の「逆向きの使い方」です。

  1. 署名(送り手):データのハッシュを計算し、それを自分の秘密鍵で変換する。これが署名。データに添えて送る。
  2. 検証(受け手):受け取ったデータから自分でもハッシュを計算。一方、署名を送り手の公開鍵で復元し、両者が一致するか比べる。
// 署名する側(秘密鍵は本人だけが持つ)
const h   = sha256(message);          // まずハッシュ(=指紋)を取り
const sig = signWithPrivateKey(h);    // 自分の秘密鍵で署名

// 検証する側(公開鍵は誰でも持てる)
const ok =
  sha256(message) === recoverWithPublicKey(sig); // 一致すれば「本人&未改ざん」
// → 1ビットでも改ざんされればハッシュがずれ、検証に落ちる
// → 秘密鍵を持たない第三者は正しい署名を作れない=なりすませない

秘密鍵を持つ本人しか作れない署名が、誰でも持てる公開鍵で検証できる。だから「本人性」が示せます。同時に、署名はハッシュに対して作られているので、中身が1ビットでも変わればハッシュがずれ、改ざんが必ずバレます。なお JWT の署名や、TLS のサーバ証明書(CA が秘密鍵で署名し、ブラウザが CA の公開鍵で検証する)も、この電子署名そのものです。

「署名」と「暗号化」を混同しない

署名は中身を隠しませんJWT のペイロードが「署名付きだから安全」と思い込み、見られて困る情報(パスワード・個人情報)を入れてしまうのは典型的な事故です。署名済み=改ざんは検知できるが、中身は誰でも読める。秘匿が必要なら別途暗号化してください。「署名(完全性・真正性)」と「暗号化(機密性)」は別の道具です。

4つの道具を一望する

守る対象(機密性・完全性・真正性)と鍵の持ち方で整理すると、役割の違いがはっきりします。

「暗号化(隠す)」と「署名(本人&改ざん検知)」「ハッシュ(指紋)」は目的が別。実システムはこれらを組み合わせて使う。
道具守るもの戻せる?代表例
共通鍵暗号機密性(秘匿)共通鍵を共有復号できる(双方向)AES-GCM
公開鍵暗号機密性+鍵配送公開鍵/秘密鍵復号できる(双方向)RSA / ECDH
ハッシュ完全性(指紋)鍵なし戻せない(一方向)SHA-256
電子署名真正性+完全性秘密鍵で署名/公開鍵で検証戻すものではないRSA / ECDSA

つまずきポイント

実務でハマりやすい誤解を、ここまでの要点として整理します。

  • 「暗号化したから安全」ではない:暗号化が守るのは機密性だけ。改ざん検知には AEAD(AES-GCM 等)や署名、なりすまし防止には署名/証明書が別途要ります。
  • 鍵を自分で実装しない:暗号の事故は「アルゴリズムが弱い」より「使い方を間違える」(IV の使い回し、ECB モード、自前のソルト生成ミスなど)で起きます。標準ライブラリ・確立した実装に任せ、自作しないのが鉄則です。
  • 乱数の質が命:鍵やソルト、IV は**暗号論的に安全な乱数(CSPRNG)**で生成します。Math.random() のような予測可能な乱数を鍵に使うと、暗号強度がゼロになります。
  • 鍵の寿命と保管:鍵やパスワードのハッシュは漏洩を前提に設計します。ローテーション(定期更新)と、秘密鍵を**秘密管理(KMS / シークレットマネージャ)**に置くことを前提に。
迷ったらの指針

隠したい(読まれたくない)→ 暗号化(少量・鍵交換なら公開鍵、大量データは共通鍵、実務はハイブリッド)。改ざんを検知したい → ハッシュ/署名本人だと証明したい → 電子署名パスワードを保存したい → bcrypt / scrypt / Argon2(汎用ハッシュ不可)。応用形として、これらを通信路で束ねたものが TLS / HTTPS です。

関連トピックとして、署名済みトークンの扱いは Cookie・セッション・JWT、暗号化通信の全体像は TLS / SSL、パスワードの保存実務は パスワードの安全な保存 を参照してください。

セキュリティ Article

暗号の基礎(共通鍵・公開鍵・ハッシュ・署名)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

暗号

比較で見る軸

難易度: basic / カテゴリ: セキュリティ / タグ数: 4

導入後に効く点

共通鍵は速いが鍵の配り方が課題。公開鍵は遅いが鍵を安全に渡せる。だから実務は両者を組み合わせる(ハイブリッド)。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
basic
カテゴリ
セキュリティ
タグ数
4

判断チェックリスト

  • 自社の用途が「暗号 / 公開鍵」に近いか確認する。
  • 強みである「暗号の道具は大きく4つ。共通鍵・公開鍵(隠す)、ハッシュ(指紋=改ざん検知)、電子署名(本人&改ざん防止)で、それぞれ目的が違う。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

暗号公開鍵ハッシュ電子署名暗号公開鍵ハッシュ電子署名
参考: 公式情報