Writeup 4 CSS CTF Semester 2 2026 Cryptography Chrono I
题目信息
- 题目名称:Chrono I
- 分值:25
- 难度:Beginner
- 题目描述:
We have intercepted a message and a Ciphertext, please help us crack the Ciphertext!
Message:
2026/09/21 14:35:07 - "As always, The time is always the key to unlock it"Ciphertext:
ESUITO{gwfvb_xejqnf_nimgt_b_whhrlv}Flag Format:
CSSCTF{...}
前置知识:维吉尼亚密码(Vigenère Cipher)
1. 什么是维吉尼亚密码
维吉尼亚密码是一种多表替换密码 ,由法国外交官布莱斯·德·维吉尼亚(Blaise de Vigenère)在 16 世纪提出。它是对凯撒密码的扩展------凯撒密码所有字母用同一个偏移量,而维吉尼亚密码每个字母使用不同的偏移量,偏移量由密钥决定。
由于同一字母在不同位置会被加密成不同密文,维吉尼亚密码在历史上曾被称为"不可破解的密码"(le chiffre indéchiffrable),直到 19 世纪才被弗里德里希·卡西斯基(Friedrich Kasiski)和查尔斯·巴贝奇(Charles Babbage)分别破解。
2. 工作原理
核心思想:用密钥的每一位对明文的每一个字母进行凯撒移位。
加密公式:
C_i = (P_i + K_i) mod 26
解密公式:
P_i = (C_i - K_i) mod 26
其中:
P_i是第 i 个明文字母的数值(A=0, B=1, ..., Z=25)K_i是第 i 个密钥字母(或数字)的值C_i是第 i 个密文字母的数值
密钥循环使用:如果密钥比明文短,密钥会从头开始重复使用。
3. 举例说明
假设:
- 明文:
HELLO - 密钥:
KEY
步骤 1:将字母转成数字(A=0, B=1, ..., Z=25)
| 明文 | H | E | L | L | O |
|---|---|---|---|---|---|
| 数值 | 7 | 4 | 11 | 11 | 14 |
| 密钥 | K | E | Y | K | E |
|---|---|---|---|---|---|
| 数值 | 10 | 4 | 24 | 10 | 4 |
步骤 2:逐位相加取模 26
| 位置 | 明文 | 密钥 | 计算 | 密文 |
|---|---|---|---|---|
| 1 | 7 | 10 | (7+10) mod 26 = 17 | R |
| 2 | 4 | 4 | (4+4) mod 26 = 8 | I |
| 3 | 11 | 24 | (11+24) mod 26 = 35 mod 26 = 9 | J |
| 4 | 11 | 10 | (11+10) mod 26 = 21 | V |
| 5 | 14 | 4 | (14+4) mod 26 = 18 | S |
密文 :RIJVS
解密 就是反过来:P_i = (C_i - K_i) mod 26
4. 数字作为密钥
维吉尼亚密码的密钥不一定是字母,也可以是数字。当密钥是数字时,直接把数字当作偏移量:
- 密钥数字
0→ 不偏移 - 密钥数字
1→ 偏移 1 - 密钥数字
9→ 偏移 9
例如密钥 202609,明文字母按 2、0、2、6、0、9 的偏移量循环加密。
5. 关键规则
在实际应用中,维吉尼亚密码有几个重要规则:
- 只加密字母:数字、标点、空格等非字母字符通常原样保留,不参与加密。
- 密钥索引只对字母递增 :遇到非字母字符时,密钥索引不前进。这意味着密钥只为字母消耗。
- 大小写敏感:大写字母加密后仍为大写,小写字母加密后仍为小写。
- 循环使用:密钥用完一遍后从头开始,直到所有字母加密完毕。
6. 破解方法
维吉尼亚密码的破解思路:
- 确定密钥长度:利用卡西斯基测试(Kasiski Examination)或弗里德曼测试(Friedman Test),找出密钥长度。
- 分组分析:将密文按密钥长度分组,每组实际上是凯撒密码。
- 频率分析:对每组进行频率分析,确定每个位置的偏移量。
- 还原密钥:将所有偏移量拼起来得到密钥。
但在 CTF 题目中,密钥通常是已知的(如本题的时间),只需直接解密即可。
解题思路
1. 分析题目提示
题目给出了两条关键信息:
- 一条消息 :
2026/09/21 14:35:07 - "As always, The time is always the key to unlock it" - 一段密文 :
ESUITO{gwfvb_xejqnf_nimgt_b_whhrlv}
提示"The time is always the key to unlock it "非常明确地告诉我们:时间就是密钥。
结合密文格式 ESUITO{...},可以猜测明文格式应为 CSSCTF{...},即密文是通过某种古典密码加密得到的。
2. 确定加密算法
密文 ESUITO 对应明文 CSSCTF,我们逐字符分析偏移:
| 密文 | 明文 | 偏移(密文 - 明文) |
|---|---|---|
| E (4) | C (2) | +2 |
| S (18) | S (18) | 0 |
| U (20) | S (18) | +2 |
| I (8) | C (2) | +6 |
| T (19) | T (19) | 0 |
| O (14) | F (5) | +9 |
偏移序列为:2, 0, 2, 6, 0, 9
这个序列正好是时间 2026/09/21 14:35:07 的前 6 位数字:202609。
继续验证密钥的完整长度:
- 时间数字提取:
2026 09 21 14 35 07→20260921143507(共 14 位) - 这是一个典型的 维吉尼亚密码 特征:密钥循环使用,每个字母按密钥数字偏移。
3. 维吉尼亚密码解密
维吉尼亚密码规则回顾:
- 加密:
C = (P + K) mod 26 - 解密:
P = (C - K) mod 26 - 其中
K是密钥数字(0-9),只对字母生效,非字母(如{、_、})跳过。 - 关键点 :密钥索引只对字母递增,遇到非字母时不消耗密钥位。
密钥 :20260921143507
解密过程:
| 字母序号 | 密文 | 密钥 | 计算 | 明文 |
|---|---|---|---|---|
| 0 | E (4) | 2 | 4-2=2 | C |
| 1 | S (18) | 0 | 18-0=18 | S |
| 2 | U (20) | 2 | 20-2=18 | S |
| 3 | I (8) | 6 | 8-6=2 | C |
| 4 | T (19) | 0 | 19-0=19 | T |
| 5 | O (14) | 9 | 14-9=5 | F |
| - | { | - | 跳过 | { |
| 6 | g (6) | 2 | 6-2=4 | e |
| 7 | w (22) | 1 | 22-1=21 | v |
| 8 | f (5) | 1 | 5-1=4 | e |
| 9 | v (21) | 4 | 21-4=17 | r |
| 10 | b (1) | 3 | 1-3=-2→24 | y |
| - | _ | - | 跳过 | _ |
| 11 | x (23) | 5 | 23-5=18 | s |
| 12 | e (4) | 0 | 4-0=4 | e |
| 13 | j (9) | 7 | 9-7=2 | c |
| 14 | q (16) | 2 | 16-2=14 | o |
| 15 | n (13) | 0 | 13-0=13 | n |
| 16 | f (5) | 2 | 5-2=3 | d |
| - | _ | - | 跳过 | _ |
| 17 | n (13) | 6 | 13-6=7 | h |
| 18 | i (8) | 0 | 8-0=8 | i |
| 19 | m (12) | 9 | 12-9=3 | d |
| 20 | g (6) | 2 | 6-2=4 | e |
| 21 | t (19) | 1 | 19-1=18 | s |
| - | _ | - | 跳过 | _ |
| 22 | b (1) | 1 | 1-1=0 | a |
| - | _ | - | 跳过 | _ |
| 23 | w (22) | 4 | 22-4=18 | s |
| 24 | h (7) | 3 | 7-3=4 | e |
| 25 | h (7) | 5 | 7-5=2 | c |
| 26 | r (17) | 0 | 17-0=17 | r |
| 27 | l (11) | 7 | 11-7=4 | e |
| 28 | v (21) | 2 | 21-2=19 | t |
得到明文:
CSSCTF{every_second_hides_a_secret}
解题脚本
python
def decrypt_vigenere(ciphertext, key):
"""
维吉尼亚密码解密
ciphertext: 密文
key: 密钥(数字字符串)
"""
plaintext = []
key_idx = 0
for ch in ciphertext:
if ch.isalpha():
shift = int(key[key_idx % len(key)])
base = ord('A') if ch.isupper() else ord('a')
plain_ch = chr((ord(ch) - base - shift) % 26 + base)
plaintext.append(plain_ch)
key_idx += 1
else:
plaintext.append(ch)
return ''.join(plaintext)
ciphertext = "ESUITO{gwfvb_xejqnf_nimgt_b_whhrlv}"
key = "20260921143507"
flag = decrypt_vigenere(ciphertext, key)
print(flag)
# 输出: CSSCTF{every_second_hides_a_secret}
运行结果:
python
C:\Users\Administrator\AppData\Local\Programs\Python\Python314\python.exe exp.py
CSSCTF{every_second_hides_a_secret}
进程已结束,退出代码为 0
关键坑点
- 密钥索引只对字母递增 :遇到
{、_、}等非字母字符时,密钥索引不前进,否则会导致后续字母解密错位。这是本题最容易出错的地方。 - 密钥长度 :完整时间数字是
20260921143507(14 位),不是前 6 位202609。 - 大小写敏感:解密时保持大小写,题目要求 flag 大小写敏感。
- 维吉尼亚密码的非字母处理:标准维吉尼亚密码只加密字母,非字母原样保留,这是实现时需要注意的细节。
最终 Flag
CSSCTF{every_second_hides_a_secret}
总结
这是一道典型的 维吉尼亚密码 入门题,考察点在于:
- 识别密码类型:通过提示"时间就是密钥"和密文格式,判断是维吉尼亚密码。
- 提取密钥:从时间格式中提取数字作为密钥。
- 正确处理密钥循环:密钥索引只对字母递增,非字母跳过,这是最容易出错的地方。
- 维吉尼亚密码的基本原理:多表替换、密钥循环、字母移位。
经验:遇到维吉尼亚密码时,密钥索引只对字母递增,非字母跳过,这是实现和解题时最关键的一点。此外,密钥不一定是字母,数字也可以作为偏移量使用,这在 CTF 题目中很常见。
Rambo
2026年国庆节
🎉🎉🎉