Crypto_XCTF_WriteUp | 轮转机加密

发布时间 2023-11-17 18:15:14作者: Guanz

题目

提示
你俩继续往前走,来到了前面的下一个关卡,这个铺面墙上写了好多奇奇怪怪的 英文字母,排列的的整整齐齐,店面前面还有一个大大的类似于土耳其旋转烤肉的架子,上面一圈圈的 也刻着很多英文字母,你是一个小历史迷,对于二战时候的历史刚好特别熟悉,一拍大腿:“嗨呀!我知道 是什么东西了!”。提示:托马斯·杰斐逊。

flag,是字符串,小写。

题目
1: < ZWAXJGDLUBVIQHKYPNTCRMOSFE <
2: < KPBELNACZDTRXMJQOYHGVSFUWI <
3: < BDMAIZVRNSJUWFHTEQGYXPLOCK <
4: < RPLNDVHGFCUKTEBSXQYIZMJWAO <
5: < IHFRLABEUOTSGJVDKCPMNZQWXY <
6: < AMKGHIWPNYCJBFZDRUSLOQXVET <
7: < GWTHSPYBXIZULVKMRAFDCEONJQ <
8: < NOZUTWDCVRJLXKISEFAPMYGHBQ <
9: < XPLTDSRFHENYVUBMCQWAOIKZGJ <
10: < UDNAJFBOWTGVRSCZQKELMXYIHP <
11: < MNBVCXZQWERTPOIUYALSKDJFHG <
12: < LVNCMXZPQOWEIURYTASBKJDFHG <
13: < JZQAWSXCDERFVBGTYHNUMKILOP <

密钥为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP

分析

一开始以为是之前学的那种 Enigma 机加密,写了代码跑一跑提交发现是错的,查了一下才知道 Enigma 机只是轮转机的一种。
这道题一共有 13 个转子,每个转子是 26 个英文字母的排列。密钥和密文皆为 13 位,和转字的数量相同。

提示提到托马斯·杰斐逊,百度了一下没找到他和轮转机的关联,遂浅看了一下大佬的 WriteUp(小声……
总的来说,密文是密钥对应转子旋转前的第一个字符,且所有转子最初按照密钥顺序排列。

按照这个原理,编写程序:

import numpy as np

rot = [list("ZWAXJGDLUBVIQHKYPNTCRMOSFE"),
       list("KPBELNACZDTRXMJQOYHGVSFUWI"),
       list("BDMAIZVRNSJUWFHTEQGYXPLOCK"),
       list("RPLNDVHGFCUKTEBSXQYIZMJWAO"),
       list("IHFRLABEUOTSGJVDKCPMNZQWXY"),
       list("AMKGHIWPNYCJBFZDRUSLOQXVET"),
       list("GWTHSPYBXIZULVKMRAFDCEONJQ"),
       list("NOZUTWDCVRJLXKISEFAPMYGHBQ"),
       list("XPLTDSRFHENYVUBMCQWAOIKZGJ"),
       list("UDNAJFBOWTGVRSCZQKELMXYIHP"),
       list("MNBVCXZQWERTPOIUYALSKDJFHG"),
       list("LVNCMXZPQOWEIURYTASBKJDFHG"),
       list("JZQAWSXCDERFVBGTYHNUMKILOP")]
key = [2, 3, 7, 5, 13, 12, 9, 1, 8, 10, 4, 11, 6]
c = "NFQKSEVOQOFNP"

# 按密文轮转
for i in range(13):
    for j in range(26):
        if rot[key[i] - 1][j] == c[i]:
            temp = rot[key[i] - 1][:j]
            rot[key[i] - 1][0:26 - j] = rot[key[i] - 1][j:]
            rot[key[i] - 1][26 - j:] = temp
            break
    print(''.join(rot[i]))
print()

# 按密钥更改转子顺序
rot_new = np.zeros((13, 26)).astype(np.str_)
for i in range(13):
    rot_new[i][0:] = rot[key[i] - 1]
    print(''.join(rot_new[i]))
print()

# 按列小写读取
for i in range(26):
    for j in range(13):
        print(rot_new[j][i].lower(), end='')
    print()

在最终输出的所有明文排列中,仅 fireinthehole 是有意义的字符串:

直接提交即可通过。

Flag

fireinthehole

参考

攻防世界-新手-crypto-转轮机加密-根本不是咖啡猫-知乎
Python list 和str互相转换的几种方法-风暴之灵-知乎
Python numpy(np)创建空的字符串数组、矩阵-蒋户川柯基-CSDN
Python中多个print内容打印在同一行-老班(Snow)-CSDN
Python字母大小写的转换(两种方法)-舍得斋-CSDN