シーザー暗号(シフト暗号)では、すべての文字を同じ数だけずらすため、鍵は25通りしかなく容易に総当たりで解読できる。では、ずらし方を統一せず、各文字を自由に別の文字に割り当てるとどうなるか? これが単一換字式暗号(Monoalphabetic Substitution Cipher)である。
単一換字式暗号の鍵空間は26! \approx 4.03 \times 10^{26}通りという天文学的な数になり、総当たり攻撃はまったく現実的でない。しかし、この膨大な鍵空間にもかかわらず、頻度分析という手法によって解読されてしまう。その構造と弱点を理解することは、暗号の安全性とは何かを考える上で重要である。
単一換字式暗号は古くから用いられていたが、その運用を効率化する道具として、1467年頃にイタリアのレオン・バッティスタ・アルベルティ(Leon Battista Alberti)が暗号円盤(Cipher Disk)を考案した。大小2枚の同心円盤の外側に平文アルファベット、内側に暗号アルファベットを配置し、内側を回転させることで換字表を素早く設定できる。アルベルティは「西洋暗号学の父」とも呼ばれている。
アルゴリズム
変換規則
単一換字式暗号の鍵は、26文字のアルファベットをどのように並び替えるかという変換規則\sigmaである。例えば、次のような対応表が一つの鍵となる。
| 平文 | 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 | I | C | O | X | Y | U | Z | P | J | K | W | L | H | B | G | S | N | R | F | T | M | L | Q | A | E |
シーザー暗号では「3文字ずらす」という一つのルールで全文字の対応が決まるが、単一換字式暗号では各文字が独立に任意の文字に対応する。この対応は重複なし(1対1対応、すなわち置換)でなければならない。
暗号化
平文の各文字を、変換規則\sigmaに従って対応する暗号文字に置き換える。
上の変換規則\sigmaを用いると:
| 平文 | a | t | t | a | c | k | a | t | d | a | w | n |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 暗号文 | D | F | F | D | C | K | D | F | O | D | L | H |
平文の「a」は常に「D」に、「t」は常に「F」に変換される。この「同じ文字は常に同じ暗号文字になる」という性質こそが、頻度分析に対する脆弱性の原因である。
鍵空間の大きさ
26文字のアルファベットの並び替え(置換)の総数は26!(26の階乗)である。
シーザー暗号(シフト暗号)の鍵空間はわずか25通りだが、単一換字式暗号は約4×1026通りである。これは地球上の海岸の砂粒の数(約1023個)の1000倍以上に相当し、1秒間に10億個の鍵を試しても、全探索に約128億年かかる計算になる。
安全性と弱点
鍵空間が巨大であるにもかかわらず、単一換字式暗号は頻度分析により解読できる。その理由は、暗号化が「文字の1対1置換」に過ぎないため、平文の統計的特徴がそのまま暗号文に反映されるからである。
英語では「E」が約12.7%の頻度で出現する。単一換字式暗号で「E→X」と変換していれば、暗号文中の「X」もやはり約12.7%の頻度で出現する。つまり、暗号文の頻度分布を英語の標準頻度と比較するだけで、文字の対応関係を推測できてしまう。
単一換字式暗号は、鍵空間が大きくても安全とは限らないことを示す好例である。暗号の安全性は鍵空間の大きさだけでなく、暗号文から平文に関する情報がどれだけ漏れるかによって決まる。
まとめ
| 項目 | 内容 |
|---|---|
| 分類 | 換字式暗号(単一換字) |
| 鍵 | 26文字の置換規則 \sigma |
| 暗号化 | c_i = \sigma(p_i) |
| 復号 | p_i = \sigma^{-1}(c_i) |
| 鍵空間 | 26! \approx 4.03 \times 10^{26} |
| 安全性 | 総当たりには耐えるが、頻度分析で解読可能 |
単一換字式暗号の弱点は、同じ平文の文字が常に同じ暗号文字に変換される点にある。この問題を根本的に解決するために、位置ごとに異なる換字表を適用するヴィジュネル暗号(多表式暗号)が考案された。
実践
下のウィジェットで単一換字式暗号を体験できる。暗号鍵(26文字の並び)を設定して暗号化・復号を試そう。「ランダム鍵」ボタンでランダムな換字表を生成できる。
Python実装
import string, random
def generate_key():
alpha = list(string.ascii_uppercase)
random.shuffle(alpha)
return ''.join(alpha)
def substitution_encrypt(plaintext, key):
table = str.maketrans(
string.ascii_lowercase + string.ascii_uppercase,
key.lower() + key.upper()
)
return plaintext.translate(table)
def substitution_decrypt(ciphertext, key):
table = str.maketrans(
key.lower() + key.upper(),
string.ascii_lowercase + string.ascii_uppercase
)
return ciphertext.translate(table)
key = "DICOXYUZPJKWLHBGSNRFTMLQAE"
ct = substitution_encrypt("attackatdawn", key)
print(f"暗号化: attackatdawn -> {ct}")
pt = substitution_decrypt(ct, key)
print(f"復号: {ct} -> {pt}")
import math
print(f"\n鍵空間: 26! = {math.factorial(26):,}")