2.1 凱薩密碼與移位密碼#
概念說明#
凱薩密碼是最古老的替代密碼之一:把明文中每個字母在字母表上往後平移固定 k 位。例如 k=3 時,A→D、B→E、Z→C。它是一種單表替代密碼——整份訊息從頭到尾使用同一張替換表。
廣義的移位密碼(shift cipher)就是把凱薩密碼的位移量一般化為任意整數 k(0~25)。金鑰空間只有 26 個,小到可以人工窮舉,因此它從來就不是安全密碼;但它是理解「替代」、「金鑰」、「模運算」三個核心概念的最佳起點。
數學描述#
把字母 A~Z 編號為 0~25,則:
- 加密:
C = (P + k) mod 26 - 解密:
P = (C - k) mod 26
其中 mod(取餘數)讓字母繞圈:Z(25) + 1 → A(0)。這是第 8 章「模運算」的第一次登場。
演算法步驟#
- 將明文統一轉為大寫、去除非字母字元(或保留原樣只處理字母)。
- 對每個字母 p,計算
(字母編號 + k) mod 26。 - 將結果編號轉回字母,得到密文。
- 解密時以
-k做同樣的運算即可。
Python 實作#
def shift_encrypt(text: str, k: int) -> str:
result = []
for ch in text:
if ch.isalpha():
base = ord('A') if ch.isupper() else ord('a')
result.append(chr((ord(ch) - base + k) % 26 + base))
else:
result.append(ch) # 非字母原樣保留
return ''.join(result)
def shift_decrypt(text: str, k: int) -> str:
return shift_encrypt(text, -k)
msg = "The Caesar cipher is easy to break"
ct = shift_encrypt(msg, 3)
print(ct) # Wkh Fdhvdu flskhu lv hdvb wr euhdn
print(shift_decrypt(ct, 3)) # 還原明文
# 窮舉攻擊:26 把金鑰全部試一次
for k in range(26):
pt = shift_decrypt(ct, k)
if "cipher" in pt:
print(f"金鑰 = {k}, 明文 = {pt}")
break
安全性分析#
- 金鑰空間只有 26:以現代運算力,窮舉不到一毫秒;即使人工,也只有 26 行可讀。這違反了「金鑰空間須足夠大」的基本要求(1.3 節)。
- 單表替代的統計弱點:即使把金鑰空間擴大(如任意打亂 26 個字母的對應,金鑰空間 26!≈4×10^26),頻率分析仍然有效——因為明文中 E 最常出現的統計特性被原封不動地帶進密文(2.2 節)。
- 已知明文攻擊直接讀出金鑰:只要知道一組明文—密文對,
k = (C - P) mod 26立即現形。
教學提醒:本節程式碼僅供理解原理,絕不可用於實務保密。
練習#
- 用 k=11 加密
ATTACK AT DAWN,再用程式解密驗證。 - 拿到一段不知金鑰的移位密文,寫一個「自動破解器」:對所有 26 個 k 計算解密結果,用英文常用字母頻率(如 E、T、A)評分,回傳最可能者。
- 若把凱薩密碼改為「每個字母移不同量」(例如依金鑰字串循環取位移量),它就變成了哪一種古典密碼?(提示:下一節會用到)