シーザー暗号(Caesar Cipher)は、暗号技術の歴史において最も古く、最も有名な暗号の一つである。古代ローマの政治家・軍人であるユリウス・カエサル(Julius Caesar, 紀元前100年頃〜紀元前44年)が、軍事通信の秘匿に用いたとされる。
ローマの歴史家スエトニウスの記録によれば、カエサルはアルファベットを3文字ずらす換字を用いて書簡を暗号化していた。ガリア戦争(紀元前58〜50年)では、敵のガリア人に通信内容を知られることなく味方と連絡を取るためにこの暗号が活用された。『ガリア戦記』には、包囲されたクィントゥス・キケロに宛てた暗号文の逸話も残されている。
カエサルの後継者アウグストゥスも同様の手法を用いたが、こちらは1文字ずらしで、アルファベットの末尾で循環させずにAAと表記したという。
シーザー暗号は単一換字式暗号(monoalphabetic substitution cipher)の最も単純な形であり、平文の各文字を一定数だけずらして暗号文を生成する。仕組みが極めてシンプルなため、暗号の基本概念を学ぶ出発点として最適である。
アルゴリズム
シーザー暗号は、鍵生成・暗号化・復号の3つのアルゴリズムから構成される。
鍵生成(KeyGen)
シーザー暗号では、ずらす文字数はn = 3に固定されている。つまり鍵は常に一つであり、鍵生成アルゴリズムは起動するとn = 3を出力するだけである。
暗号化(Enc)
アルファベットの各文字に0〜25の番号を割り当てる(A=0, B=1, ..., Z=25)。平文の文字xに対して、暗号化関数は次のように定義される。
復号(Dec)
暗号文の文字yに対して、復号関数は次のとおりである。
換字表
シーザー暗号(n = 3)の対応表は次のとおりである。平文を小文字、暗号文を大文字で表記する慣例に従う。
| 平文 | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 暗号文 | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | A | B | C |
各文字を数値に変換し、暗号化関数を適用する。
よって、平文「hello」の暗号文は「KHOOR」となる。
図解
シーザー暗号の換字対応を図に示す。上段が平文、下段が暗号文で、各文字が3文字分ずれて対応している。暗号化では上から下へ、復号では下から上へ読み替える。
シフト暗号への一般化
シーザー暗号ではずらす文字数がn = 3に固定されているが、これを任意の数nに拡張したものをシフト暗号(Shift Cipher)と呼ぶ。シフト暗号はROTnとも表記される(ROTはRotate=回転の意)。
n = 0のとき平文と暗号文が一致してしまうため除外される。鍵空間はn = 1からn = 25までの25通りしかない。
復号で左にn文字ずらすことは、右に26 - n文字ずらすことと同等である。つまり、ずらす値として26 - nを入力すれば、暗号化アルゴリズムで復号も行える。
ROT13
シフト暗号の中でも特に有名なのがROT13(n = 13)である。英語のアルファベットは26文字であるため、ROT13を2回適用すると元の平文に戻るという性質を持つ。
この性質により、暗号化と復号に同じ操作を使える。UNIXシステムではネタバレ防止やジョークの隠蔽などにrot13コマンドが利用されてきた。
安全性と弱点
シーザー暗号(およびシフト暗号)は、現代の基準では暗号としての安全性をまったく持たない。主な弱点は以下の2つである。
総当たり攻撃(Brute Force Attack)
鍵空間がわずか25通りしかないため、すべての鍵を試すだけで解読できる。コンピュータはもちろん、手作業でも短時間で全パターンを列挙可能である。
暗号文「KHOOR」に対し、n = 1から順に左シフトを試す。
| n | 復号結果 | n | 復号結果 |
|---|---|---|---|
| 1 | JGNNQ | 14 | WTAAD |
| 2 | IFMMP | 15 | VSZZC |
| 3 | HELLO | 16 | URYYB |
| 4 | GDKKN | 17 | TQXXA |
| 5 | FCJJM | 18 | SPWWZ |
| 6 | EBIIL | 19 | ROVVY |
n = 3で「HELLO」という意味のある英単語が出現するため、鍵は3であると判明する。
頻度分析(Frequency Analysis)
シフト暗号では、平文中の各文字が常に同じ暗号文字に変換される。そのため、暗号文中の文字の出現頻度を調べることで鍵を推定できる。英語では「E」が最も頻出する文字(約12.7%)であるため、暗号文中で最も多い文字が「E」に対応すると仮定すれば、ずらし量が逆算できる。
2006年、イタリアのマフィアのボスであるベルナルド・プロヴェンツァーノが逮捕された。彼の通信にはシーザー暗号の変種(A=4, B=5, ...のように数字に置き換える方式)が使われており、その解読が逮捕の手がかりの一つとなった。
まとめ
| 項目 | 内容 |
|---|---|
| 分類 | 単一換字式暗号(シフト暗号の特殊ケース) |
| 鍵 | n = 3(固定) |
| 暗号化 | E(x) = (x + 3) \bmod 26 |
| 復号 | D(y) = (y - 3) \bmod 26 |
| 鍵空間(シフト暗号) | 25通り |
| 安全性 | 極めて低い(総当たり・頻度分析で容易に解読) |
シーザー暗号は単純すぎて実用的な安全性を持たないが、この弱点を克服するために、ずらし量を位置ごとに変えるヴィジュネル暗号(Vigenère Cipher)が16世紀に考案された。
実践
下のウィジェットでシーザー暗号(シフト暗号)を体験できる。ずらし量を変えて、暗号化・復号の動作を確認してみよう。
Python実装
Pythonによるシーザー暗号(シフト暗号)の実装を示す。暗号化・復号・総当たり攻撃の3つの機能を含む。
def caesar_encrypt(text, n):
result = []
for c in text:
if c.isalpha():
base = ord('A') if c.isupper() else ord('a')
result.append(chr((ord(c) - base + n) % 26 + base))
else:
result.append(c)
return ''.join(result)
def caesar_decrypt(text, n):
return caesar_encrypt(text, -n)
# 暗号化
plaintext = "Hello, World!"
ciphertext = caesar_encrypt(plaintext, 3)
print(f"暗号化: {plaintext} -> {ciphertext}")
# 復号
decrypted = caesar_decrypt(ciphertext, 3)
print(f"復号: {ciphertext} -> {decrypted}")
# 総当たり攻撃
print("\n--- 総当たり攻撃 ---")
target = "KHOOR"
for i in range(1, 26):
print(f"n={i:2d}: {caesar_decrypt(target, i)}")