CTFCrypto题解:fanfie——Base32+仿射密码的组合加密

admin 2026-03-05 19:55:34 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档详细讲解了一道名为fanfie的CTF密码学题目解法,核心在于识别Base32编码与仿射密码的组合加密机制。作者利用已知明文攻击推导出仿射密码的参数,构建解密映射表还原Base32字符串,最终解码得到flag。文章结构清晰,数学推导严谨,并提供了完整的Python解题脚本,适合密码学初学者学习已知明文攻击与古典密码分析方法。 综合评分: 90 文章分类: CTF,逆向分析


cover_image

CTF Crypto 题解:fanfie —— Base32 + 仿射密码的组合加密

原创

破镜安全 破镜安全

破镜安全

2026年3月5日 08:00 四川

CTF Crypto 题解:fanfie —— Base32 + 仿射密码的组合加密

题目信息

  • 题目名称:fanfie
  • 题目类型:Crypto(密码学)
  • 附件cd0e90cf13d54d048177008444b29c0b.txt

附件内容只有一行:

MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI

题目描述告诉我们:flag 被转换为 Base32 编码,然后以某种方式加密。


第一步:理解 Base32 编码

在正式分析密文之前,需要先了解 Base32 是什么。

Base32 是一种将任意二进制数据编码为可打印 ASCII 字符的编码方案。它使用以下 32 个字符作为字母表:

字符: 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 2 3 4 5 6 7
数值: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

注意:Base32 的字符集不包含数字 0 和 1(避免与字母 O、I 混淆),以及大写字母 A-Z 加上数字 2-7,共 32 个字符,每个字符代表一个 5 位的二进制值(因为 2^5 = 32)。

Base32 编码时,每 5 个字节(40 位)的原始数据被编码为 8 个 Base32 字符,不足时用 = 号填充。


第二步:确定明文结构,提取已知明文

根据题目描述和 CTF 比赛的惯例,该比赛的 flag 格式为 BITSCTF{...}

我们观察密文长度:MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI 共 35 个字符。

已知:

  • 原始明文先经过 Base32 编码,再经过某种加密得到密文
  • Base32 编码结果只包含 A-Z 和 2-7 这 32 个字符

这意味着密文本身就是一个被加密过的 Base32 字符串。我们可以对密文做字符级别的统计分析。

现在,利用已知的 flag 前缀 BITSCTF{ 来做已知明文攻击。

先对 BITSC(flag 的前 5 个字节)做 Base32 编码:

import base64
base64.b32encode(b"BITSC")
# 输出: b'IJEVIU2D'

所以 flag 明文 BITSCTF{...} 经过 Base32 编码后,开头 8 个字符为 IJEVIU2D

这 8 个字符对应密文的开头 8 个字符为 MZYVMIWL

我们得到了 8 组已知的明文-密文字符对:

明文 Base32:  I  J  E  V  I  U  2  D
密文:          M  Z  Y  V  M  I  W  L

第三步:判断加密方式——单字母替换密码

观察以上对应关系:

  • 明文中 I 出现了两次(位置 1 和位置 5),密文中两次都对应 M
  • 相同的明文字符始终对应相同的密文字符
  • 不同的明文字符对应不同的密文字符(V 对应 V,但其他字符都发生了变化)

这是典型的**单字母替换密码(Monoalphabetic Substitution Cipher)**的特征:明文字母表中每个字符固定映射到密文字母表中的一个字符,且这个映射是一一对应的。

单字母替换密码的常见形式包括:凯撒密码、ROT13、仿射密码等。


第四步:识别仿射密码,推导参数

现在将已知对应关系转换为数值(使用 Base32 字母表中的位置编号):

明文字符 -> 数值    密文字符 -> 数值
I        ->  8       M        -> 12
J        ->  9       Z        -> 25
E        ->  4       Y        -> 24
V        -> 21       V        -> 21
U        -> 20       I        ->  8
2        -> 26       W        -> 22
D        ->  3       L        -> 11

仿射密码的加密公式为:

E(x) = (a * x + b) mod m

其中:

  • x 是明文字符的数值
  • m 是字母表大小(这里 m = 32)
  • ab 是待确定的参数,且 a 必须与 m 互质(即 gcd(a, 32) = 1)

利用任意两对已知明文-密文对建立方程组:

取 I(8) -> M(12) 和 J(9) -> Z(25)

(a * 8 + b) mod 32 = 12   ...(1)
(a * 9 + b) mod 32 = 25   ...(2)

(2) – (1):

a * (9 - 8) mod 32 = (25 - 12) mod 32
a mod 32 = 13
所以 a = 13

将 a = 13 代入方程 (1):

13 * 8 + b ≡ 12 (mod 32)
104 + b ≡ 12 (mod 32)
8 + b ≡ 12 (mod 32)   (因为 104 mod 32 = 8)
b = 4

验证 a = 13 与 m = 32 是否互质:

gcd(13, 32) = 1  ✓(13 是质数,且不是 2 的因子)

用全部已知对验证加密公式 E(x) = (13 * x + 4) mod 32

| 明文字符 | 明文数值 x | 计算值 (13x+4) mod 32 | 密文数值 | 密文字符 | 是否匹配 | | — | — | — | — | — | — | | I | 8 | (104+4) mod 32 = 12 | 12 | M | 匹配 | | J | 9 | (117+4) mod 32 = 25 | 25 | Z | 匹配 | | E | 4 | (52+4) mod 32 = 24 | 24 | Y | 匹配 | | V | 21 | (273+4) mod 32 = 21 | 21 | V | 匹配 | | U | 20 | (260+4) mod 32 = 8 | 8 | I | 匹配 | | 2 | 26 | (338+4) mod 32 = 22 | 22 | W | 匹配 | | D | 3 | (39+4) mod 32 = 11 | 11 | L | 匹配 |

所有对均验证通过,确认加密参数为 a = 13,b = 4,m = 32


第五步:构建完整的加密字母表(辅助理解)

用加密公式 E(x) = (13x + 4) mod 32 计算 Base32 字母表中每个字符的加密映射:

明文: 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  2  3  4  5  6  7
密文: E  R  6  L  Y  F  S  7  M  Z  G  T  A  N  2  H  U  B  O  3  I  V  C  P  4  J  W  D  Q  5  K  X

这是一张完整的替换表,明文中任意一个 Base32 字符都可以在这张表中找到对应的密文字符。


第六步:解密——求仿射密码的逆变换

已知加密公式 E(x) = (a * x + b) mod m,解密公式为:

D(y) = a_inv * (y - b) mod m

其中 a_inv 是 a 在模 m 意义下的乘法逆元,满足:

a * a_inv ≡ 1 (mod m)

求 a = 13 在模 32 下的逆元,即找整数 a_inv 使得 13 * a_inv ≡ 1 (mod 32)

13 * 5 = 65 = 2 * 32 + 1
所以 13 * 5 mod 32 = 1
a_inv = 5

解密公式为:

D(y) = 5 * (y - 4) mod 32

第七步:对密文逐字符解密

对密文 MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI 的每个字符应用解密公式:

base32_alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
a_inv = 5
b = 4
m = 32

ciphertext = "MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI"
plaintext_b32 = ""
for c in ciphertext:
    ci = base32_alpha.index(c)          # 找到字符的数值
    pi = (a_inv * (ci - b)) % m        # 仿射解密
    plaintext_b32 += base32_alpha[pi]  # 还原字符

解密结果为:

密文:        MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI
仿射解密后:  IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU

第八步:Base32 解码,还原 flag

仿射解密后得到的字符串 IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU 就是原始 flag 经过 Base32 编码后的形式。

注意 Base32 解码时需要考虑填充。Base32 每 8 个字符为一组,不足时用 = 填充。IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU 共 35 个字符,35 mod 8 = 3,需要补 6 个 = 号。

(Base32 填充规则:编码长度必须是 8 的倍数,35 个字符的下一个 8 的倍数是 40,需要补 5 个 =。实际上标准补 6 个也被接受,用 Python 的 base64 库验证即可。)

import base64
base64.b32decode('IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU======')
# 输出: b'BITSCTF{S2VyY2tob2Zm}'

得到 flag:BITSCTF{S2VyY2tob2Zm}


完整解题脚本

import base64

# Base32 字母表(32个字符,每个字符代表0-31的数值)
base32_alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
m = 32

# 仿射密码参数(通过已知明文攻击推导得出)
a, b = 13, 4
a_inv = 5  # 13 的模 32 乘法逆元:13 * 5 ≡ 1 (mod 32)

# 目标密文
ciphertext = "MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI"

# 第一步:仿射解密,还原 Base32 编码字符串
plaintext_b32 = ""
for c in ciphertext:
    ci = base32_alpha.index(c)
    pi = (a_inv * (ci - b)) % m
    plaintext_b32 += base32_alpha[pi]

# 第二步:Base32 解码,添加 padding
flag = base64.b32decode(plaintext_b32 + "======").decode()

print(f"密文:        {ciphertext}")
print(f"仿射解密后:  {plaintext_b32}")
print(f"flag:        {flag}")

运行结果:

密文:        MZYVMIWLGBL7CIJOGJQVOA3IN5BLYC3NHI
仿射解密后:  IJEVIU2DKRDHWUZSKZ4VSMTUN5RDEWTNPU
flag:        BITSCTF{S2VyY2tob2Zm}

知识点总结

1. 已知明文攻击(Known-Plaintext Attack)

在 CTF 中,flag 格式通常是已知的(如 BITSCTF{)。利用这部分已知信息,可以直接推导出密钥参数,而不需要穷举所有可能的密钥。这是密码分析中最基础也最重要的技术手段之一。

2. 仿射密码(Affine Cipher)

仿射密码是凯撒密码的推广。凯撒密码只有加法偏移(即 a=1 的特例),而仿射密码同时包含乘法和加法两种变换:

  • 加密:E(x) = (a * x + b) mod m
  • 解密:D(y) = a_inv * (y – b) mod m

约束条件:a 必须与 m 互质,这是为了保证加密映射是一一对应的(双射),从而可以唯一解密。

3. 组合编码与加密

本题的加密流程是:明文 -> Base32编码 -> 仿射加密 -> 密文。理解这个流程是解题的关键。仿射加密作用在 Base32 字符层面,而非原始字节层面,因此需要用 Base32 字母表(32个字符)作为仿射密码的字母表,模数 m = 32。

4. 题目名称的彩蛋

题目名称 “fanfie” 是 “affine”(仿射)的字母变位(anagram),暗示了加密算法的类型。在 CTF 解题中,题目名称往往包含重要提示。


Flag

BITSCTF{S2VyY2tob2Zm}

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:破镜安全 破镜安全 破镜安全《CTF Crypto 题解:fanfie —— Base32 + 仿射密码的组合加密》

评论:0   参与:  0