暗号技術は、私たちの日常生活に欠かせないセキュリティの基礎です。インターネット上での通信やデータの保存など、あらゆる場面で「情報を守るための仕組み」が活躍しています。今回は「共通鍵暗号(対称鍵暗号)」をテーマに、その基本的な仕組みと簡単なPythonコードを用いた実践例を分かりやすく解説していきます。
1. 共通鍵暗号とは?
共通鍵暗号(対称鍵暗号)は、「送信者と受信者が同じ秘密鍵を共有して」暗号化と復号を行う方式です。
- 暗号化: 共通鍵(秘密鍵)を使って平文(暗号化する前の読みやすいメッセージ)を暗号文に変換する
- 復号: 共通鍵(秘密鍵)を使って暗号文を平文に戻す
なぜ「共通鍵」かというと、暗号化と復号に使う鍵が同じ(または平文から導ける関係にある)ためです。これに対し、公開鍵暗号方式は「公開鍵」と「秘密鍵」が別々である点が大きく異なります。
共通鍵暗号のメリット・デメリット
- メリット
- 処理が比較的高速で、大量のデータを暗号化・復号しやすい。
- 公開鍵暗号に比べて、実装がシンプルな場合が多い。
- デメリット
- 鍵の管理: 送信者と受信者はあらかじめ安全に鍵を共有する必要がある。
- 鍵の使い回しリスク: 通信相手ごとに安全に鍵を生成・交換しなければならない。
2. 共通鍵暗号の種類
共通鍵暗号には大きく以下の2種類があります。それぞれ、暗号化を行う単位(ブロックまたはビット/バイト)に注目すると分かりやすいです。
- ブロック暗号
メッセージ(平文)を一定の長さ(ブロック)に分割し、各ブロックを暗号化していきます。- 代表的な例: DES、3DES、AES など。
- 64ビットや128ビットなど、ブロックサイズを固定して暗号化を行う。
- ストリーム暗号
メッセージをビットまたはバイト単位で、逐次的に暗号化していきます。- XOR演算を使うシンプルな仕組みのものが多い。
- 音声や動画など、ストリーミングのようにリアルタイムで処理するケースに向いている。
3. ブロック暗号の代表例: DES(Data Encryption Standard)
DESの概要
- ブロック長: 64ビット
- 鍵長: 56ビット(実質的に 8バイト x 7ビット = 56ビット)
- 構造: 16段階の「ファイステル構造」を用いて複雑な変換を行う
1977年に米国政府によって標準化され、長く使われてきた暗号方式です。しかし、現代の計算機パワーでは解読リスクが高いとされ、現在は「3DES」や「AES」が主流となっています。
Pythonによる簡易DES暗号化の例
以下は、Pythonのライブラリ「PyCryptodome」を使ってDESの暗号化・復号を行う簡単なサンプルコードです。ブロック暗号のイメージをつかむための例となります。
from Crypto.Cipher import DES
import secrets
# 8バイトの秘密鍵を生成(DESでは鍵長が56ビット有効)
secret_key = secrets.token_bytes(8)
# 平文を定義(DESブロック長の8バイトに合わせる)
plaintext = "HELLO!!!".encode() # 8文字
# ECBモード(Electronic Codebook)で暗号器を作成
cipher = DES.new(secret_key, DES.MODE_ECB)
# 暗号化
encrypted_text = cipher.encrypt(plaintext)
print("暗号文:", encrypted_text)
# 復号化
decrypted_text = cipher.decrypt(encrypted_text)
print("復号結果:", decrypted_text.decode())
実行結果の例:
暗号文: b'\x92\x1d\xe7\x94\x12g\xec\x1b'
復号結果: HELLO!!!
モード(動作モード)について
上の例では、最も基本的なモードであるECBモードを使用しています。ECBモードはブロックごとに独立して暗号化を行うため、同じ平文ブロックは同じ暗号文ブロックになりやすい、という弱点があります。実際に運用で使う場合には、CBC、CFB、OFB、CTR、GCMなどの他のモードが推奨されます。これらは初期化ベクトル(IV)を用いることで、ブロックごとの暗号化パターンをより複雑にし、セキュリティを強化する仕組みを持っています。
4. ストリーム暗号の仕組み
ストリーム暗号では、平文をビットやバイト単位で逐次的に暗号化していきます。代表的な方法として、鍵ストリーム(疑似乱数系列)を生成し、それと平文をXOR演算することで暗号化を行う手法があります。
- XOR演算: 0と1を比較し、異なる場合に1、同じ場合に0を返す演算。
- 同じ鍵ストリームを用いて暗号文とXORすれば、元の平文が復元できる。
Pythonによるストリーム暗号の例
こちらもシンプルなXORベースの実装例です。あくまで基礎の理解のためのサンプルコードなので、実際のセキュリティ用途には、より安全な疑似乱数生成器を用いることが望まれます。
def xor_encrypt_decrypt(data, key):
return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)])
# 平文と鍵を定義
plaintext = "STREAM ENCRYPTION".encode()
key = b'secret'
# 暗号化
encrypted = xor_encrypt_decrypt(plaintext, key)
print("暗号文:", encrypted)
# 復号化
decrypted = xor_encrypt_decrypt(encrypted, key)
print("復号結果:", decrypted.decode())
実行結果の例:
暗号文: b'*\x1eL\x0bX...(省略)'
復号結果: STREAM ENCRYPTION
5. 共通鍵暗号の安全性と注意点
5.1 共通鍵暗号の安全性と注意点
共通鍵暗号方式の最大の課題は「鍵を安全に共有する」ことです。インターネット上で鍵をそのまま送ると盗聴されるリスクがあるため、実際のシステムでは以下のような方法が用いられます。
- 公開鍵暗号を使って共通鍵を安全にやり取りする(ハイブリッド暗号)
- オフラインで安全に鍵を交換する(物理的なやり取り)
- VPNなどの安全なチャンネルでキー交換を行う
5.2 鍵の使い回しリスク
一度盗まれた鍵は、すべての通信を復号される可能性があります。複数の相手と通信する場合には使い捨てキーやセッションキーの導入を検討し、定期的にキーを更新することでリスクを下げることが重要です。
5.3 暗号解読手法の進歩
DESの解読リスクが高まったことから、より長い鍵長や複雑な構造を持つ暗号方式(3DES、AESなど)が利用されています。また、ブロック暗号でもモード選択を誤るとセキュリティが低下することがあるため、暗号利用モードには注意が必要です。
6. まとめ
共通鍵暗号は、高速かつ大量のデータを効率的に暗号化できる利点があり、日常的な通信の暗号化に広く使われています。
- DESや3DES、AESなどのブロック暗号
- ストリーム暗号(RC4など)
一方で、共通鍵暗号の最も大きな課題は鍵の安全な配布・管理であり、その弱点を補うために公開鍵暗号を組み合わせたハイブリッド方式が一般的に用いられます。実際のシステムでは、ライブラリや暗号プロトコル(TLS/SSLなど)を正しく利用することで、安全な通信やデータ保存を実現しています。
今回のサンプルコードでは最も単純な手法を紹介しましたが、実務レベルではAES、ChaCha20などのより安全な暗号アルゴリズムと、安全なモード(例: CBC、GCMなど)を用いることが推奨されます。ぜひ実際にコードを実行してみることで、暗号の仕組みを体感してみてください!
付録: より実践的な暗号化のTips
- AES(Advanced Encryption Standard)を使う
- 128ビットブロックサイズで、128/192/256ビットの鍵長をサポートする。
- DESよりも安全性が高く、処理も高速。
- 暗号利用モードの活用
- ECBモードは平文のパターンが暗号文に反映されやすい。
- CBCやGCMモードなど、初期化ベクトル(IV)を用いたモードが推奨される。
- 鍵の生成と保存
secrets.token_bytes()
や安全な乱数生成器を使う。- 鍵は暗号化された形で保存し、アクセス制限を厳格にする。
- キー交換には公開鍵暗号を併用
- 安全なチャンネルがない場合、RSAやDH(ディフィー・ヘルマン)を用いてセッションキーを生成・交換する。
- TLS/SSLなどのプロトコルは内部でこの仕組みを使っている。
- 定期的な鍵の更新(キーローテーション)
- 鍵の漏洩や長期利用によるリスクを下げるため、定期的に新しい鍵に切り替える仕組みを導入する。
コメント