概要
暗号技術には大きく分けて「共通鍵暗号(対称鍵暗号)」と「公開鍵暗号(非対称鍵暗号)」の二つの方式がある。両者は仕組みも特性も異なり、現代の暗号システムは両者を組み合わせて使うハイブリッド方式が主流となっている。
共通鍵暗号は、暗号化と復号に同じ鍵を使う方式。高速で計算コストが低いため、大量データの暗号化に適する。欠点は「鍵をどうやって安全に相手と共有するか」という鍵配送問題である。
公開鍵暗号は、誰でも参照できる「公開鍵」と厳重に秘匿する「秘密鍵」のペアを使う方式。鍵配送問題を解決するが、計算コストが高く大量データの暗号化には向かない。
現実のシステムでは、「公開鍵暗号で共通鍵を安全に交換し、その後は共通鍵暗号で通信する」という組み合わせが標準的である。
歴史・背景
- 1949年: Claude Shannon が「通信の秘密理論」を発表し、現代暗号理論の基盤を築く。
- 1976年: Whitfield Diffie と Martin Hellman が「暗号における新方向」を発表し、公開鍵暗号の概念を提唱。鍵配送問題を理論的に解決した革命的論文。
- 1977年: Ronald Rivest、Adi Shamir、Leonard Adleman が RSA 暗号を発表。公開鍵暗号の最初の実用実装。
- 1985年: Neal Koblitz と Victor Miller が楕円曲線暗号(ECC)を独立に提案。短い鍵で高いセキュリティを実現。
- 2001年: NIST が AES(Advanced Encryption Standard)を標準化。Rijndael アルゴリズムを採用。
- 2005年〜: ECC ベースの ECDH、ECDSA が TLS や組み込みシステムで普及開始。
- 2022年: NIST が量子コンピュータへの耐性を持つ PQC(耐量子暗号)アルゴリズムを選定。CRYSTALS-Kyber(鍵交換)、CRYSTALS-Dilithium(署名)など。
技術仕様
共通鍵暗号(対称鍵暗号)
| アルゴリズム | 鍵長 | ブロック長 | 特徴 |
|---|---|---|---|
| AES-128 | 128 bit | 128 bit | 現在の主流、高速 |
| AES-256 | 256 bit | 128 bit | より高セキュリティ |
| ChaCha20 | 256 bit | ストリーム | ソフトウェア実装高速 |
| 3DES | 168 bit | 64 bit | 旧式、非推奨 |
| DES | 56 bit | 64 bit | 廃止(安全でない) |
動作速度の目安(ARM Cortex-M4 @ 120MHz、ソフトウェア実装):
AES-128-GCM(SW): ≈ 2〜5 MB/s
AES-128-GCM(HW): ≈ 50〜200 MB/s (ハードウェアアクセラレータ)
ChaCha20-Poly1305: ≈ 5〜15 MB/s
公開鍵暗号(非対称鍵暗号)
| アルゴリズム | 用途 | 鍵長 | 速度 | 推奨度 |
|---|---|---|---|---|
| RSA-2048 | 暗号化・署名 | 2048 bit | 遅い | 互換性重視 |
| RSA-4096 | 高セキュリティ署名 | 4096 bit | 非常に遅い | 高セキュリティ |
| ECDSA P-256 | 署名 | 256 bit | 速い | 現在の主流 |
| ECDH P-256 | 鍵交換 | 256 bit | 速い | 現在の主流 |
| Ed25519 | 署名 | 256 bit | 最速 | 新規実装推奨 |
| X25519 | 鍵交換 | 256 bit | 最速 | 新規実装推奨 |
セキュリティ強度の等価比較:
RSA-1024 ≈ AES-80 (廃止)
RSA-2048 ≈ AES-112 (現在許容範囲)
RSA-3072 ≈ AES-128 (推奨)
RSA-15360 ≈ AES-256 (将来的な高セキュリティ)
ECC P-256 ≈ AES-128 (推奨)
ECC P-384 ≈ AES-192 (高セキュリティ)
動作原理
共通鍵暗号の仕組み
送信者 受信者
│ │
│ 同じ鍵 K を事前に共有 │
│ │
│ 平文 P │
│ ──→ [AES-GCM 暗号化(K)] ──→ 暗号文 C + Tag
│ │
│ │ 暗号文 C + Tag
│ │ ──→ [AES-GCM 復号(K)] ──→ 平文 P
│ │
└───────────────────────────────────┘
※ 鍵 K を安全に共有するのが課題(鍵配送問題)
公開鍵暗号の仕組み(RSA 暗号化)
受信者: 公開鍵(e, n) を公開、秘密鍵(d, n) を秘匿
送信者 受信者
│ 公開鍵(e, n) を取得 │
│ │
│ 暗号化: C = P^e mod n │
│ ──────────────────────────────→ │
│ │ 復号: P = C^d mod n
│ │ ※ d は誰にも渡さない
ECDH 鍵交換の仕組み
Alice Bob
│ │
│ 秘密 a を生成 │ 秘密 b を生成
│ 公開 A = a × G を計算 │ 公開 B = b × G を計算
│ │
│ A を Bob に送信 │
│─────────────────────────────────→
│ │
│←─────────────────────────────── │ B を Alice に送信
│ │
│ 共有秘密 = a × B │ 共有秘密 = b × A
│ = a × b × G │ = b × a × G
│ │ ← 同じ値になる!
│ │
※ 盗聴者が A と B を見ても a×b×G は計算できない(楕円曲線離散対数問題)
Python での実装例
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
# ===== ECDH 鍵交換 =====
# Alice 側: X25519 鍵ペア生成
alice_private = X25519PrivateKey.generate()
alice_public = alice_private.public_key()
# Bob 側: X25519 鍵ペア生成
bob_private = X25519PrivateKey.generate()
bob_public = bob_private.public_key()
# 鍵交換: 共通の共有秘密を生成
alice_shared = alice_private.exchange(bob_public)
bob_shared = bob_private.exchange(alice_public)
assert alice_shared == bob_shared # 同じになる
# ===== 共通鍵暗号(AES-GCM) =====
# 共有秘密から共通鍵を導出(HKDF 等を使うべきだが、簡略化)
aes_key = alice_shared[:16] # 実際は HKDF で導出
# AES-GCM で暗号化
aesgcm = AESGCM(aes_key)
nonce = os.urandom(12) # 毎回ランダムに生成
plaintext = b"Hello, IoT World!"
ciphertext = aesgcm.encrypt(nonce, plaintext, None)
# 復号
decrypted = aesgcm.decrypt(nonce, ciphertext, None)
assert decrypted == plaintext
# ===== Ed25519 署名 =====
private_key = Ed25519PrivateKey.generate()
public_key = private_key.public_key()
message = b"firmware_v1.2.3"
signature = private_key.sign(message)
# 検証
public_key.verify(signature, message) # 問題なければ例外なし
C 言語での ECDH + AES-GCM(Mbed TLS)
#include "mbedtls/ecdh.h"
#include "mbedtls/gcm.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
/* ECDH 鍵交換で共有秘密を生成 */
int ecdh_key_exchange(uint8_t *shared_secret, size_t *secret_len) {
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ecdh_init(&ctx);
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
/* 乱数生成器の初期化 */
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&entropy, NULL, 0);
/* ECDH グループ(P-256)の設定 */
mbedtls_ecdh_setup(&ctx, MBEDTLS_ECP_DP_SECP256R1);
/* 鍵ペアの生成と公開鍵の送信(省略)*/
/* 相手の公開鍵の受信(省略)*/
/* 共有秘密の計算 */
mbedtls_ecdh_calc_secret(&ctx, secret_len, shared_secret, 32,
mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_ecdh_free(&ctx);
return 0;
}
用途・ユースケース
TLS ハンドシェイクでのハイブリッド暗号
TLS 1.3 では ECDH で鍵交換を行い、その結果得られた共有秘密から AES-GCM または ChaCha20-Poly1305 の共通鍵を導出して通信を暗号化する。
IoT デバイスのプロビジョニング
工場出荷時に各デバイスに固有の ECC 鍵ペアを生成し、公開鍵をクラウドに登録する。以後の通信は ECDSA 署名によるデバイス認証と ECDH による鍵交換で保護される。
コード署名
ファームウェア署名では、Ed25519 や ECDSA P-256 の秘密鍵で署名し、デバイス内の公開鍵で検証する。
実装・開発のポイント
アルゴリズム選択のガイドライン
新規実装の推奨:
鍵交換: X25519(ECDH Curve25519)
署名: Ed25519
共通鍵: AES-256-GCM または ChaCha20-Poly1305
ハッシュ: SHA-256
MCU リソース制約がある場合:
署名: ECDSA P-256(HW アクセラレータ利用可能な場合)
共通鍵: AES-128-GCM または AES-128-CCM
ハッシュ: SHA-256
互換性重視(既存システムとの連携):
鍵交換: ECDH P-256
署名: RSA-2048 または ECDSA P-256
量子コンピュータへの備え
現在の RSA・ECC は将来の量子コンピュータで破られる可能性がある。長期的なデータ保護が必要なシステムでは NIST PQC 標準への移行計画を立てておく。
他技術との比較
| 観点 | 共通鍵暗号 | 公開鍵暗号 |
|---|---|---|
| 鍵の種類 | 1種類(共有鍵) | 2種類(公開鍵+秘密鍵) |
| 速度 | 高速(10〜1000倍) | 低速 |
| 鍵配送問題 | あり | なし(公開鍵を安全に配布できる) |
| 主な用途 | データ暗号化、通信暗号化 | 鍵交換、デジタル署名、認証 |
| 代表例 | AES, ChaCha20 | RSA, ECDSA, ECDH, Ed25519 |
現代のセキュアシステムは「公開鍵暗号で鍵交換→共通鍵暗号でデータ保護」というハイブリッド方式を採用する。TLS/DTLS がこのパターンの典型例であり、IoT 通信セキュリティの標準的な設計基盤となっている。