CTF学记之棋盘密码

2023.10.25

Polybius

棋盘密码是利用波利比奥斯方阵(Polybius Square)进行加密的密码方式,产生于公元前两世纪的希腊,相传是世界上最早的一种密码。

密码表

12345
1ABCDE
2FGHI/JK
3LMNOP
4QRSTU
5VWXYZ

示例:

以FLAG为例

FLAG
密文21311122

代码解密实现 

def polybius_decode(ciphertext):
    num,x,y = 0,0,0;text = '';checkerboard = ['abcde','fghik','lmnop','qrstu','vwxyz']
    for i in ciphertext:
        if ord('1')<=ord(i)<=ord('5'):
            if num%2 == 0:
                x = int(i)-1
            else:
                y = int(i)-1
                text += checkerboard[x][y]
            num += 1
        else:
            text += i
    return text

ADFGX 

1918年,第一次世界大战将要结束时,法军截获了一份德军电报,电文中的所有单词都由A、D、F、G、X五个字母拼成,因此被称为ADFGX密码。ADFGX密码是1918年3月由德军上校FritzNebel发明的,是结合了波利比奥斯方阵和置换密码的双重加密方案。

ADFGX密码之所以选择ADFGX一个字母,是因为它们译成摩斯密码时不容易混淆,可以降低传输错误的机率。

密码表:

ADFGX
AABCDE
DFGHI/JK
FLMNOP
GQRSTU
XVWXYZ

ps:密码表的字母顺序可自定义 

示例:

以明文:flag,秘钥:key

第一步:按密码表生成密码文

FLAG
编码DAFAAADD

 第二步:利用移位钥匙加密

设钥匙字是“key”,将之写在新格子的第一列

再将上一阶段的密码文一列一列写进新方格里

key
DAF
AAA
DD

第三步:

按照钥匙字字母顺序「eky」依次抄下该字下整行讯息,形成新密文

AAD DAD FA

解密脚本实现:

def adfgx_decode(ciphertext):
    #判断密文是否正确
    def check(ciphertext):
        ciphertext = ''.join([i for i in ciphertext if i in dic])
        if len(ciphertext) %2 != 0:return False
        for i in ciphertext:    
            if i not in dic and i != ' ':return False
        return True
    dic={'A':0,'D':1,'F':2,'G':3,'X':4}
    if not check(ciphertext):return '密文错误'
    #判断关键字是否正确
    while True:
        key = input('请输入关键字:\n')
        if not key.isalpha():return '关键字错误'  
        else:break
    #判断棋盘是否正确
    s = 'abcdefghiklmnopqrstuvwxyz'
    while True:
        s = input('请输入棋盘序列:\n')
        if len(s) != 25 : print('长度错误,请重输')
        else : break
    checkerboard = [s[:5],s[5:10],s[10:15],s[15:20],s[20:]]
    #分配密文
    list_key,list_1= [i for i in key],[]
    ciphertext = ''.join([i for i in ciphertext if i in dic])
    num = len(ciphertext)
    a = [1 for i in range(num%len(key))]+[0 for i in range(len(key)-num%len(key))]
    for i in range(len(key)):
        for j in range(i,len(key)):
            if list_key[i] > list_key[j]:
                list_key[i],list_key[j] = list_key[j],list_key[i]
                a[i],a[j] = a[j],a[i]
    for i in range(len(key)):
        if a[i] == 1:
            list_1.append(ciphertext[:num // len(key) + 1])
            ciphertext = ciphertext[num // len(key) + 1:]
        else:
            list_1.append(ciphertext[:num // len(key)])
            ciphertext = ciphertext[num // len(key):]
    #还原排序
    for i in range(len(key)):
        for j in range(i,len(list_key)):
            if key[i] == list_key[j]:
                list_key[i],list_key[j] = list_key[j],list_key[i]
                list_1[i],list_1[j] = list_1[j],list_1[i]
    string_1 =''.join([list_1[j][i] for i in range(len(list_1[0])) for j in range(len(list_1)) if len(list_1[j]) > i])
    #解码
    text = ''
    for i in range(len(string_1)):
        if i %2 == 0: x = string_1[i]
        else:
            y = string_1[i]
            text += checkerboard[dic[x]][dic[y]]
    return text

ADFGVX 

在 1918年 6月,再加入一个字 V 扩充。变成以 6 × 6 格共 36 个字符加密。这使得所有英文字母(不再将 I 和 J 视为同一个字)以及数字 0 到 9 都可混合使用。这次增改是因为以原来的加密法发送含有大量数字的简短信息有问题。

ADFGVX
AABCDEJ
DFGHIK9
FLMNOP8
GQRSTU7
VVWXYZ6
X012345

 编码规则和ADFGX一样

解码脚本实现:

def adfgvx_decode(ciphertext):
    #判断密文是否正确
    def check(ciphertext):
        ciphertext = ''.join([i for i in ciphertext if i in dic])
        if len(ciphertext) %2 != 0:return False
        for i in ciphertext:
            if i not in dic and i != ' ':return False
        return True
    dic={'A':0,'D':1,'F':2,'G':3,'V':4,'X':5}
    if not check(ciphertext):return '密文错误'
    #判断关键字是否正确
    while True:
        key = input('请输入关键字:\n')
        if not key.isalnum():return '关键字错误'  
        else:break
    #判断棋盘是否正确
    s = 'abcdefghijklmnopqrstuvwxyz0123456789'
    while True:
        s = input('请输入棋盘序列:\n')
        if len(s) != 36 : print('长度错误,请重输')
        else : break
    checkerboard = [s[:6],s[6:12],s[12:18],s[18:24],s[24:30],s[30:]]
    #分配密文
    list_key,list_1= [i for i in key],[]
    ciphertext = ''.join([i for i in ciphertext if i in dic])
    num = len(ciphertext)
    a = [1 for i in range(num%len(key))]+[0 for i in range(len(key)-num%len(key))]
    for i in range(len(key)):
        for j in range(i,len(key)):
            if list_key[i] > list_key[j]:
                list_key[i],list_key[j] = list_key[j],list_key[i]
                a[i],a[j] = a[j],a[i]
    for i in range(len(key)):
        if a[i] == 1:
            list_1.append(ciphertext[:num // len(key) + 1])
            ciphertext = ciphertext[num // len(key) + 1:]
        else:
            list_1.append(ciphertext[:num // len(key)])
            ciphertext = ciphertext[num // len(key):]
    #还原排序
    for i in range(len(key)):
        for j in range(i,len(list_key)):
            if key[i] == list_key[j]:
                list_key[i],list_key[j] = list_key[j],list_key[i]
                list_1[i],list_1[j] = list_1[j],list_1[i]
    string_1 =''.join([list_1[j][i] for i in range(len(list_1[0])) for j in range(len(list_1)) if len(list_1[j]) > i])
    #解码
    text = ''
    for i in range(len(string_1)):
        if i %2 == 0: x = string_1[i]
        else:
            y = string_1[i]
            text += checkerboard[dic[x]][dic[y]]
    return text
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z时代.bug(゜▽゜*)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值