古典密碼學
Cryptography & Classical Ciphers
2025 建北電資聯合暑訓
講師 Suzy
- 我是 Suzy
- 很廢的學術長(?
- 奇怪技能多,但大概都是沒什麼用的那種
- 應該是 I 人,但教課的時候會盡量 E
- 備這堂課最常做的事情是唱 ABCDEFG 的歌,
你等一下就知道為什麼了

Suzy Sheep
課程大綱
1. What is 密碼學
2. 數字系統
3. 各種經典密碼
4. 無法破解的密碼?
5. 現代密碼學(簡介)
6. 成果發表
7. CTF 題單
What is 密碼學
Cryptography
= kryptos + graphein
秘密
書寫
研究如何加密資訊的學科
What is 密碼學
古典
密碼學
現代
密碼學
- 沒有電腦的年代
- 用紙筆即可操作

20 世紀後
(有電腦的年代)

故事時間


最早的密碼
古埃及
斯巴達密碼棒

故事時間

古希臘傳輸軍事訊息的方法
- 發明者:Aeneas Tacticus
- 第一個考量軍事訊息傳輸的戰術家
發訊息者用火炬告訴接收訊息者要「放水」的時間
在相同時間放水就會顯示出相同的紙條

古希臘 波利比烏斯方表
準備 10 個火炬
5 個用來表示行
5 個用來表示列
只能傳輸已經寫在紙條上的訊息
可以傳輸任何訊息
數字系統
Number Systems
10 進制
60 進制
12 進制
24 進制
5 進制
進位制
進位制:什麼意思?
這是十進位制的例子:
進位制:什麼意思?
由此可知,數字可以這樣表示:
十進位制時,
進位制:二進位制
同理,二進位制就是
先理解邏輯再思考怎麼把數字從 13 轉換成 1101
- Binary
進位制:二進位制 & 十進位制 的轉換
進位制:二進位制 & 十進位制 的轉換
進位制:Base 16
- 十六進位制
- Hexadecimal
- Base 16
十進位制 => 10 個符號
二進位制 => 2 個符號
十六進位制 => ?
進位制:Base 16
十六進位制顯然需要 16 個符號!
不過它的思考邏輯和其他進位制是相同的。
怪怪的?
進位制:Base 16
怪怪的。
如果用 0~15 作為 Base 16 ,會出事。
所以 10 ~ 15 用 A ~ F 代替
如何將數值在二進位制和十六進位制間轉換?
(不是很重要,有空再講)
小實作
數字系統
decimal = int(input( ))
binary = bin(decimal)[2:]
print(binary)
Python 實作
# 試試看自己用 hex 做 base 16 吧
# 作法和 binary 一樣Python 實作
# base 64 比較麻煩一點
import base64
n = int(input())
byte_len = (n.bit_length() + 7) // 8 or 1
byte_data = n.to_bytes(byte_len, 'big')
b64_str = base64.b64encode(byte_data).decode('utf-8')
print(b64_str)
Python 實作
關於編碼
ENCODING
Base 64
有用+常見 = 可以學一下
目標:改善二進位資料的易讀性
- 如果位元個數不是 6 的整數倍,就在數字後面補 0 讓位元個數變成 6 的整數倍
- 將二進位制的資料,每 6 個位元分為一節,換成十進位制
Base 64

Base 64
ASCII
Base 64
ASCII
Binary
Base 64
每 6 個位元為一個單位,換回用 10 進位制表示
Base 64
剩下的數字補 0,直到位元個數為 6 的整數倍為止
Base 64
查前面 Base 64 的表!
Base 64 的應用

摩斯密碼
ASCII 編碼

ASCII 編碼:為什麼 A 是 65?

A = 100 0001
B = 100 0010
中文字在電腦中是如何儲存的?
Unicode
可以表示將近十萬個字元,包含各種語言的符號以及表情符號等
關於 ASCII、Unicode 和 UTF-8 的故事
小實作
編碼
Python 體驗:圖片編碼
複製 .txt 裡的內容到瀏覽器上,就可以看到圖片了!
古典密碼學
Classical Ciphers
名詞定義
- 明文= 尚未加密的原始資料
- 密文= 經過加密處理後無法直接閱讀的資料
- 加密= 將明文轉為密文的過程
- 解密= 將密文轉為明文的過程
- 密鑰= 即 key, 加密與解密過程中使用的「祕密參數」,決定如何將明文轉換為密文,或將密文還原為明文。
凱薩密碼
Caesar Cipher
對我們終於進入重點了
凱薩密碼:
- 最經典的古典密碼(應該?)
- 用「替換」的方式
最簡單的替換:字母換字母
模運算
餘數

這樣就是 key = -3
小實作
凱薩密碼
C++ 實作
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
int key;
// 輸入要加密/解密的字串
getline(cin, str);
cin >> key;基礎設置
輸入字串
為什麼用 getline?
C++ 實作
for (int i=0; i< int(str.size()); i++) {
char c = str[i];
// 判斷字元是大小、小寫或空格/標點符號,並依 key 進行轉換
// mod 26 避免算出 >26 的數值
if (isupper(c)) {
cout << char((c - 'A' + key + 26) % 26 + 'A');
}
else if (islower(c)) {
cout << char((c - 'a' + key + 26) % 26 + 'a');
}
else {
cout << c;
// 這一行若是寫成 continue; 就可以忽略空格和標點符號喔
}
}
破解
凱薩密碼
- 凱薩密碼顯然很不安全
- 凱薩大王發明的(?
- 凱薩年代多數人不識字 => 密碼安全性不重要

如何破解?
- 當然可以暴力 (brute force) 反正最多 25 種 key
- 但有沒有更快的方法呢?
頻率分析

拉丁字母只有 26 個,其中有一些特別常出現。
猜猜看哪些字母最常出現?
想法:
只要找出密文中最常出現的字母,假設它是 e 或 t 等,就可以推算出 key 值了!
頻率分析
限制:密文要夠長才有用。(太短的文字中,最常出現的字母不一定是英文中最常出現的字母)
Znkyk ykixkz iovnkxy ckxk aykj zu qkkv skyygmky nojjkt.
頻率分析
破解看看?
- 方法不限,可以用手算、可以用程式。
- 為了假裝我們是原古時代的人類且為避免 GPT plus 用戶佔優勢,禁用生成式 AI。
頻率分析
Python 實作(補充)
維吉尼亞密碼
Vigenere Cipher
- 改良版的凱薩密碼
- 凱薩密碼出現的1500 年後才有人發明這個改良
想法:還是和凱薩密碼類似的「替換」,但 key 值不只一個。
- 每個字母都以一個數值表示
- 決定 key 的長度。
- 決定 key 的每一個數值(即偏移量)。
- 依照 key 所指定的數值,替換字母,且不斷循環 key 直到明文裡的每個字母都已替換為止。
維吉尼亞 例子
- key 是 25, 5, 19 (YES)
- 明文是 CKEFGISC
做做看?
維吉尼亞 查表

小實作
維吉尼亞密碼
C++ 實作
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 我們這次東西有比較多喔// 輸入明文和key
int main() {
string str, key;
vector<int> key_val;
getline(cin, str);
cin >> key;基礎設置
輸入明文 和 key
C++ 實作
for (int i = 0; i < int(key.size()); i++) {
key_val.push_back(toupper(key[i]) - 'A');
}
for (int i = 0; i < int(str.size()); i++) {
char c = str[i];
int shift = key_val[i % key_val.size()];
if (isupper(c)) {
cout << char((c - 'A' + shift + 26) % 26 + 'A');
} else if (islower(c)) {
cout << char((c - 'a' + shift + 26) % 26 + 'a');
} else {
cout << c;
}
}
// 分流處理(?把 key 換成數值
破解
維吉尼亞密碼
- 維吉尼亞密碼顯然比較難用暴力破解,畢竟我們需要知道 key 的長度及確切數值。
所以沒辦法用頻率分析嗎?
其實可以!
1. 知道 key 的長度
2. 依照 key 的循環,把對應到相同 key 數值的字母分為同一組。
3. 以一組一組為單位,進行頻率分析。
如何知道 key 的長度
單表代換密碼
多表代換密碼


ex: 凱薩密碼
ex: 維吉尼亞密碼
1) 字母的分佈
如何知道 key 的長度
單表代換密碼
多表代換密碼
ex: 凱薩密碼
ex: 維吉尼亞密碼
1) 字母的分佈


如何知道 key 的長度
2) 重合因子 Index of Coincidence
- 重合因子 = 從明文裡任選兩個字母,選到相同字母的機率
- 機率問題:選到一個特定字母的機率是多少?

總共有 1000 個字母
其中有 73 個 A
選到 1 個 A 的機率
選第 2 個字母,又選到 A 的機率
如何知道 key 的長度
2) 重合因子 Index of Coincidence

I.C. 約 0.066

I.C. 約 0.038
單表代換密碼
多表代換密碼
如何知道 key 的長度
3) 假設不同的 key 長度,並分組計算 I.C.

密文
例:如果 key 長度是 2,則 I.C. 為 0.05842
如何知道 key 的長度
3) 假設不同的 key 長度,並分組計算 I.C.
密文
例:如果 key 長度是 3,則 I.C. 為 0.04765

如何知道 key 的長度
3) 假設不同的 key 長度,並分組計算 I.C.
密文
例:如果 key 長度是 3,則 I.C. 為 0.04765

如何知道 key 的長度
3) 假設不同的 key 長度,並分組計算 I.C.

尋找 I.C. 較接近 0.066 的,
非常有可能是 key 的長度!
知道 key 的長度之後呢?
其實就變成凱薩密碼了!
Apsqwaaed Ganlwpw yvw zwpc dyf.Xzcc yvw isqc rs zvwyo.G sk dcejlmfe lm vcgjwtl ganlwpw yx rlw GCCJYGWU wmkqwp uyqh xgbeq.
key 長度 = 3,則以 3 為循環分組
第一組
第二組
第三組
知道 key 的長度之後呢?
第一組
第二組
第三組
因為每一組內的 key 值都相同,所以可以想成像是 3 個獨立的凱薩密碼,針對每一組做頻率分析即可破解!(=要做 3 次頻率分析)
無法破解的密碼
存在嗎?
「無法破解」是什麼意思
1. 人類運算資源不足,導致非常難破解(幾乎不可能)Ex: 現代密碼
2. 真的無法破解,即使用無限的運算資源也無法破解。
第二種類型的密碼,存在嗎?
「無法破解」是什麼意思
其實存在!而且甚至是古典密碼
一次性密碼本 One - time Pad
- 無論是凱薩密碼或維吉尼亞密碼,「頻率分析」都需要仰賴「密鑰的規律性」
- 如果密鑰和明文一樣長,就不能使用頻率分析了
成果發表
請用這堂課所學 or 其他你自己想到的東西
製作一個密碼。
規則:
1. 不能是凱薩密碼或維吉尼亞密碼
2. 不一定要是能用程式實作出來的密碼
3. 可以上網查資料
4. 需準備明文、及密文的例子
方案 1
方案 2
請各小隊選擇一個方案,作為古典密碼學課程的成果發表
從 5 題中任選 3 題完成,規則及題目都在以下文件中:
2025 暑訓 古典密碼學
By Suzy Huang
2025 暑訓 古典密碼學
- 172