WP007——CTF赛题解析-行置换解码

114 阅读2分钟

时效性

2025年7月26日

题目来源

散乱的密文 - Bugku CTF平台

题目描述

image.png

Write Up

随波逐流:行置换解码 key为 216534

image.png

总结

加密原理:

  1. 创建表格:将明文按行写入一个宽度为 nn 的表格(nn 为密钥长度)
  2. 列置换:按照密钥指定的列顺序读取列(密钥是数字 1 到 nn 的排列)
  3. 生成密文:按新顺序连接所有列

解密原理:

  1. 计算逆置换:根据密钥推导出列的正确位置
  2. 重构表格:将密文按列写入表格(使用逆置换顺序)
  3. 读取明文:按行读取表格内容
def row_transposition_encrypt(plaintext, key):
    """
    行置换加密
    :param plaintext: 明文字符串
    :param key: 置换密钥 (整数列表)
    :return: 密文字符串
    """
    n = len(key)
    # 计算需要填充的字符数
    padding = (n - len(plaintext) % n
    if padding:
        plaintext += 'X' * padding  # 用X填充
    
    # 创建表格
    rows = len(plaintext) // n
    table = [list(plaintext[i*n:(i+1)*n]) for i in range(rows)]
    
    # 按密钥顺序读取列
    ciphertext = []
    for col_index in key:
        col_index -= 1  # 转换为0-based索引
        for row in range(rows):
            ciphertext.append(table[row][col_index])
    
    return ''.join(ciphertext)

def row_transposition_decrypt(ciphertext, key):
    """
    行置换解密
    :param ciphertext: 密文字符串
    :param key: 置换密钥 (整数列表)
    :return: 明文字符串
    """
    n = len(key)
    rows = len(ciphertext) // n
    
    # 计算逆置换密钥
    inv_key = [0] * n
    for idx, val in enumerate(key):
        inv_key[val-1] = idx + 1  # 计算列的正确位置
    
    # 创建空表格
    table = [[''] * n for _ in range(rows)]
    
    # 按逆置换顺序填充列
    pos = 0
    for col_index in inv_key:
        col_index -= 1  # 转换为0-based索引
        for row in range(rows):
            table[row][col_index] = ciphertext[pos]
            pos += 1
    
    # 按行读取明文
    plaintext = ''.join(''.join(row) for row in table)
    return plaintext.rstrip('X')  # 移除填充字符

# 测试示例
if __name__ == "__main__":
    # 示例密钥 (必须是1~n的排列)
    key = [3, 1, 4, 2]  # 表示:先读取第3列,然后第1列,然后第4列,最后第2列
    
    plaintext = "HELLO WORLD"
    print("原始明文:", plaintext)
    
    # 加密
    ciphertext = row_transposition_encrypt(plaintext, key)
    print("加密结果:", ciphertext)  # 输出: LWDHORLOXEL
    
    # 解密
    decrypted = row_transposition_decrypt(ciphertext, key)
    print("解密结果:", decrypted)  # 输出: HELLO WORLD