CTF BUUOJ Cipher:Playfair 密码解密实战–从“公平的玩吧”到获取 Flag

一、题目描述

在做 CTF 密码学题目时,遇到了一道非常有意思的题目,题目描述如下:

Cipher
1
还能提示什么呢?公平的玩吧(密钥自己找)

Dncnoqqfliqrpgeklwmppu

注意: 得到的 flag 请包上 flag{} 提交, flag{小写字母}

二、题目分析

1. 确定加密算法

题目中最关键的提示是中文 “公平的玩吧”
在密码学中,提到“公平”,最经典的对应算法就是 Playfair Cipher(Playfair 密码)。
Playfair 密码(Playfair cipher)是一种对称式密码,也是第一种双字母替换密码。它的基本原理是使用一个 5x5 的矩阵来对明文进行加密。

2. 确定密钥

题目中提到“密钥自己找”。既然提示已经指向了 Playfair 算法,根据 CTF 出题的常见套路,我们大胆猜测密钥就是算法的名字本身。
因此,猜测密钥为:playfair

三、手动解密过程

为了深入理解算法,我们先尝试手动解密。

1. 构造密钥矩阵

Playfair 使用一个 5x5 的矩阵。构造规则如下:

  1. 去除密钥中的重复字母。
  2. 将剩余字母填入矩阵。
  3. 剩余位置按字母表顺序填充(通常 I/J 合并,标准 Playfair 中 J 被 I 替代)。
    密钥: playfair
    去重后得到序列:p, l, a, y, f, i, r
    填充剩余字母,得到最终的 5x5 矩阵:
    | | 1 | 2 | 3 | 4 | 5 |
    |—|—|—|—|—|—|
    | 1 | P | L | A | Y | F |
    | 2 | I | R | B | C | D |
    | 3 | E | G | H | K | M |
    | 4 | N | O | Q | S | T |
    | 5 | U | V | W | X | Z |

2. 分组解密

密文:Dncnoqqfliqrpgeklwmppu
将密文两两分组:Dn, cn, oq, qf, li, qr, pg, ek, lw, mp, pu
Playfair 解密规则(与加密相反):

  1. 同行:向移动一位。
  2. 同列:向移动一位。
  3. 不同行不同列:对角线交换(矩形法则),取同行的另一个角。
    具体解密步骤解析:
  • Dn: D(2,5), N(4,1) -> 不同行列 -> 取对角 I(2,1), T(4,5) -> IT
  • cn: C(2,4), N(4,1) -> 不同行列 -> 取对角 I(2,1), S(4,4) -> IS
  • oq: O(4,2), Q(4,3) -> 同行左移 -> N(4,1), O(4,2) -> NO
  • qf: Q(4,3), F(1,5) -> 不同行列 -> 取对角 T(4,5), A(1,3) -> TA
  • li: L(1,2), I(2,1) -> 不同行列 -> 取对角 P(1,1), R(2,2) -> PR
  • qr: Q(4,3), R(2,2) -> 不同行列 -> 取对角 O(4,2), B(2,3) -> OB
  • pg: P(1,1), G(3,2) -> 不同行列 -> 取对角 L(1,2), E(3,1) -> LE
  • ek: E(3,1), K(3,4) -> 同行左移 -> M(3,5), H(3,3) -> MH
  • lw: L(1,2), W(5,3) -> 不同行列 -> 取对角 A(1,3), V(5,2) -> AV
  • mp: M(3,5), P(1,1) -> 不同行列 -> 取对角 E(3,1), F(1,5) -> EF
  • pu: P(1,1), U(5,1) -> 同列上移 -> U(5,1), N(4,1) -> UN
    拼接解密结果:
    IT IS NO TA PR OB LE MH AV EF UN
    整理明文并去除填充:
    IT IS NOT A PROBLEM HAVE FUN (明文为:这不是个问题,玩得开心)

四、Python 脚本自动化解密

在实际比赛中,为了节省时间,我们可以编写 Python 脚本来自动处理。以下是完整的解密代码:

def playfair_decrypt(ciphertext, key):
    """
    Playfair 密码解密函数
    :param ciphertext: 密文
    :param key: 密钥
    :return: 明文
    """
    # 1. 预处理密钥:去重、转大写、J转I
    key = key.upper().replace('J', 'I')
    seen = set()
    processed_key = []
    for char in key:
        if char not in seen and char.isalpha():
            seen.add(char)
            processed_key.append(char)
    
    # 2. 生成字母表并构建矩阵
    # 标准Playfair字母表不含J
    alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
    for char in alphabet:
        if char not in seen:
            processed_key.append(char)
            seen.add(char)
            
    # 构建 5x5 矩阵
    matrix = [processed_key[i:i+5] for i in range(0, 25, 5)]
    
    # 辅助函数:查找字符在矩阵中的位置
    def find_pos(char):
        for r in range(5):
            for c in range(5):
                if matrix[r][c] == char:
                    return r, c
        return None
    # 3. 解密逻辑
    ciphertext = ciphertext.upper().replace('J', 'I')
    plaintext = ""
    
    # 每两个字符一组进行解密
    for i in range(0, len(ciphertext), 2):
        char1 = ciphertext[i]
        char2 = ciphertext[i+1]
        
        r1, c1 = find_pos(char1)
        r2, c2 = find_pos(char2)
        
        # 规则 1: 同一行 -> 左移一位
        if r1 == r2:
            plaintext += matrix[r1][(c1 - 1) % 5]
            plaintext += matrix[r2][(c2 - 1) % 5]
        # 规则 2: 同一列 -> 上移一位
        elif c1 == c2:
            plaintext += matrix[(r1 - 1) % 5][c1]
            plaintext += matrix[(r2 - 1) % 5][c2]
        # 规则 3: 矩形对角交换
        else:
            plaintext += matrix[r1][c2]
            plaintext += matrix[r2][c1]
            
    return plaintext
if __name__ == "__main__":
    # 题目数据
    cipher_text = "Dncnoqqfliqrpgeklwmppu"
    key = "playfair" 
    
    # 执行解密
    result = playfair_decrypt(cipher_text, key)
    
    # 格式化输出 Flag
    # 题目要求 flag{小写字母}
    flag = f"flag{{{result.lower()}}}"
    
    print("-" * 30)
    print(f"Key: {key}")
    print(f"Plaintext: {result}")
    print(f"Flag: {flag}")
    print("-" * 30)

运行结果:

------------------------------
Key: playfair
Plaintext: ITISNOTAPROBLEMHAVEFUN
Flag: flag{itisnotaproblemhavefun}
------------------------------

五、总结

这道题的考点主要有两个:

  1. 脑洞与联想:通过“公平”二字联想到 Playfair 密码。
  2. 基础密码学知识:掌握 Playfair 密码的矩阵构造和解密规则。
    最终的 Flag 为:
flag{itisnotaproblemhavefun}

希望这篇 WriteUp 对你有所帮助!如果有任何疑问,欢迎在评论区留言交流。

觉得有用的话,点个赞再走吧!👍

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐