暗号化の基礎 - 対称鍵 vs 非対称鍵、開発者が知るべきこと
AES、RSA、HTTPSの仕組みを知らないなら、この記事を読んでください。暗号化の核心概念を実践的な例で解説します。
Toolypet Team
Development Team
暗号化の基礎:対称鍵 vs 非対称鍵
「このデータを暗号化して送ってください。」
この言葉を聞いたとき、何をどうすればいいか正確にわかりますか?
暗号化には大きく2つの方式があります。それぞれいつ使うかを知らないと、セキュリティ設計を間違える可能性があります。
暗号化 vs ハッシュ化
まず、混同しやすい概念を整理します。
| 暗号化 | ハッシュ化 | |
|---|---|---|
| 方向 | 双方向(復号可能) | 一方向(復号不可) |
| 目的 | データ保護 | 整合性確認、パスワード保存 |
| 鍵が必要 | はい | いいえ |
| 例 | AES, RSA | SHA-256, bcrypt |
暗号化:元のデータを復元できる ハッシュ化:元のデータを復元できない
パスワード保存にはハッシュ化、データ転送には暗号化を使用します。
対称鍵暗号化
概念
1つの鍵で暗号化し、同じ鍵で復号します。
平文 + 鍵 → 暗号化 → 暗号文
暗号文 + 鍵 → 復号 → 平文
例:鍵と錠前
家の鍵を考えてください。同じ鍵で施錠し、同じ鍵で解錠します。
代表的なアルゴリズム
| アルゴリズム | 鍵長 | 状態 |
|---|---|---|
| AES-256 | 256bit | 現在の標準 |
| AES-128 | 128bit | 安全 |
| 3DES | 168bit | レガシー |
| DES | 56bit | 脆弱 |
コード例(Node.js)
const crypto = require('crypto');
// 鍵生成(実際には安全に保存する必要あり)
const key = crypto.randomBytes(32); // AES-256
const iv = crypto.randomBytes(16); // 初期化ベクトル
// 暗号化
function encrypt(text) {
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// 復号
function decrypt(encrypted) {
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
const secret = "機密データ";
const encrypted = encrypt(secret);
const decrypted = decrypt(encrypted);
console.log(encrypted); // "a3f8b2c1..."
console.log(decrypted); // "機密データ"
メリット・デメリット
| メリット | デメリット |
|---|---|
| 高速 | 鍵共有問題 |
| 大容量データに適している | 鍵が漏洩したら終わり |
| 実装が簡単 | 鍵管理が複雑 |
鍵共有問題
AがBに暗号化されたメッセージを送りたい場合、Bに鍵を先に渡す必要があります。
しかし、その鍵をどうやって安全に渡すのでしょうか?
この問題を解決するのが非対称鍵暗号化です。
非対称鍵暗号化
概念
2つの鍵を使用します:
- 公開鍵(Public Key):誰に知られても良い
- 秘密鍵(Private Key):絶対に公開してはいけない
公開鍵で暗号化 → 秘密鍵のみで復号
秘密鍵で署名 → 公開鍵で検証
例:郵便ポスト
- 公開鍵 = 郵便ポスト(誰でも手紙を入れられる)
- 秘密鍵 = ポストの鍵(持ち主だけが手紙を取り出せる)
代表的なアルゴリズム
| アルゴリズム | 用途 | 鍵長 |
|---|---|---|
| RSA | 暗号化、署名 | 2048+ bit |
| ECDSA | 署名 | 256+ bit |
| Ed25519 | 署名 | 256bit |
コード例(Node.js RSA)
const crypto = require('crypto');
// 鍵ペア生成
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
});
// 公開鍵で暗号化
function encryptWithPublic(text) {
return crypto.publicEncrypt(publicKey, Buffer.from(text)).toString('base64');
}
// 秘密鍵で復号
function decryptWithPrivate(encrypted) {
return crypto.privateDecrypt(privateKey, Buffer.from(encrypted, 'base64')).toString();
}
const secret = "機密データ";
const encrypted = encryptWithPublic(secret);
const decrypted = decryptWithPrivate(encrypted);
console.log(decrypted); // "機密データ"
デジタル署名
秘密鍵で署名すると、公開鍵で誰が署名したか確認できます。
// 秘密鍵で署名
const sign = crypto.createSign('SHA256');
sign.update('メッセージ');
const signature = sign.sign(privateKey, 'base64');
// 公開鍵で検証
const verify = crypto.createVerify('SHA256');
verify.update('メッセージ');
const isValid = verify.verify(publicKey, signature, 'base64');
console.log(isValid); // true
メリット・デメリット
| メリット | デメリット |
|---|---|
| 鍵共有問題を解決 | 遅い(対称鍵の1000倍) |
| デジタル署名が可能 | 大容量データに不向き |
| 公開鍵を自由に配布可能 | 鍵長が長い |
実践:両方を組み合わせて使用(ハイブリッド暗号化)
これがHTTPSの仕組みです。
プロセス
1. サーバー:RSA公開鍵/秘密鍵を生成
2. クライアント:サーバーの公開鍵を受け取る
3. クライアント:AESセッションキーを生成
4. クライアント:セッションキーをRSA公開鍵で暗号化 → サーバーに送信
5. サーバー:RSA秘密鍵でセッションキーを復号
6. 両者:AESセッションキーでデータを暗号化して通信
なぜこうするのか
- RSA:鍵交換にのみ使用(遅いが安全)
- AES:実際のデータ暗号化に使用(高速)
それぞれの長所だけを使用します。
実務チェックリスト
対称鍵(AES)使用時
- AES-256またはAES-128を使用
- 暗号化ごとに新しいIV(初期化ベクトル)を生成
- 鍵は環境変数またはKMSに保存
- ECBモードは使用禁止(CBC、GCMを使用)
非対称鍵(RSA)使用時
- 最低2048bit鍵を使用
- 秘密鍵は絶対に公開しない
- OAEPパディングを使用(PKCS#1 v1.5は避ける)
- 鍵ローテーションポリシーを策定
FAQ
Q:APIキーを暗号化して保存すべきですか?
A:暗号化よりも環境変数やシークレット管理ツール(AWS Secrets Manager、HashiCorp Vault)を使用してください。暗号化しても復号鍵の管理問題が残ります。
Q:クライアントサイドで暗号化すれば安全ですか?
A:いいえ。クライアントのコードは誰でも見られるため、鍵が露出します。機密性の高い暗号化はサーバーサイドで行うべきです。
Q:SHA-256も暗号化ですか?
A:いいえ。SHA-256はハッシュ化です。復号できません。データを復元する必要がある場合は、AESのような暗号化を使用してください。
まとめ
| シナリオ | 使用アルゴリズム |
|---|---|
| 大容量データ暗号化 | AES-256 |
| 鍵交換 | RSA, ECDH |
| デジタル署名 | RSA, ECDSA, Ed25519 |
| パスワード保存 | bcrypt, Argon2(ハッシュ化) |
| HTTPS通信 | ハイブリッド(RSA + AES) |
関連ツール
著者について
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.