前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >四方密码

四方密码

作者头像
安恒网络空间安全讲武堂
发布2018-12-14 14:52:35
2K0
发布2018-12-14 14:52:35
举报

原理&简介

四方密码是一种对称式加密法,由法国人Felix Delastelle发明。这种方法将字母两个一组,然后采用多字母替换密码。四方密码用4个5×5的矩阵来加密。每个矩阵都有25个字母。

英文中有26个字母,所以一般是去掉其中的Q或者将i和j当做一样。

四方密码有4个矩阵(有两个秘钥矩阵,两个顺序矩阵)。

加密

可以选取两个英文作为两个秘钥,例如hello和world,去除其中相同的字母,于是秘钥变成了helo和world。

将第一个秘钥矩阵放在右上角,第二个秘钥矩阵放在左下角,两个顺序矩阵分别放在左上角和右下角,如下图:

例如我们要对字符串“I am not a drug god”进行加密,首先将明文分组,分为“ia m not ad rug g od”,找出分组中第一个字母在左上角矩阵的位置i(二行四列),第二个字母在右下角矩阵的位置a(一行一列),第一个密文为第一个字母的行号和第二个字母的列号B(二行一列),第二个密文为第一个字母的列号和第二个字母的行号L(一行四列),如下图所示,正好是个四方的形状:

使用python编写加密脚本如下:

代码语言:javascript
复制
#coding:utf-8

import collections
import re

matrix = "ABCDEFGHIJKLMNOPRSTUVWXYZ"
pla = "abcdefghijklmnoprstuvwxyz"
key1 = "[HELLO]"
key2 = "[WORLD]"
key1 = ''.join(collections.OrderedDict.fromkeys(key1))
key2 = ''.join(collections.OrderedDict.fromkeys(key2))

matrix1 = re.sub('[\[\]]','',key1) + re.sub(key1,'',matrix)
matrix2 = re.sub('[\[\]]','',key2) + re.sub(key2,'',matrix)

matrix_list1 = []
matrix_list2 = []
pla_list = []
for i in range(0,len(matrix1),5):
    matrix_list1.append(list(matrix1[i:i+5]))
#print matrix_list1

for i in range(0,len(matrix2),5):
    matrix_list2.append(list(matrix2[i:i+5]))
#print matrix_list2

for i in range(0,len(pla),5):
    pla_list.append(list(pla[i:i+5]))
#print pla_list


#查询明文字母位置
def find_index(x):
    for i in range(len(pla_list)):
        for j in range(len(pla_list[i])):
            if pla_list[i][j] == x:
                return i,j

def gen_cip(letter):

    #两个子母中第一个字母位置
    first = find_index(letter[0])

    #两个子母中第二个字母位置
    second = find_index(letter[1])

    cip = ""
    cip += matrix_list1[first[0]][second[1]]
    cip += matrix_list2[second[0]][first[1]]

    return cip

def encrypt(pla):
    #pla = "whereismysecretkey"
    cip = ""
    for i in range(0,len(pla),2):
        cip += gen_cip(pla[i:i+2])
    return cip

def main():
    pla = "i am not a drug god"
    pla = pla.replace(' ','')
    print encrypt(pla)

if __name__ == "__main__":
    main()

运行结果如下:

解密:

同样是将密文分组,找出分组中第一个字母在右上角矩阵的位置B(二行一列),第二个字母在左下角矩阵的位置L(一行四列),第一个明文为第一个字母的行号和第二个字母的列号i(二行四列),第二个明文为第一个字母的列号和第二个字母的行号a(一行一列),如下图所示:

使用python编写解密脚本如下:

代码语言:javascript
复制
#coding:utf-8
import collections
import re

matrix = "ABCDEFGHIJKLMNOPRSTUVWXYZ"
pla = "abcdefghijklmnoprstuvwxyz"
key1 = "[HELLO]"
key2 = "[WORLD]"
key1 = ''.join(collections.OrderedDict.fromkeys(key1))
key2 = ''.join(collections.OrderedDict.fromkeys(key2))

matrix1 = re.sub('[\[\]]','',key1) + re.sub(key1,'',matrix)
matrix2 = re.sub('[\[\]]','',key2) + re.sub(key2,'',matrix)

matrix_list1 = []
matrix_list2 = []
pla_list = []
for i in range(0,len(matrix1),5):
    matrix_list1.append(list(matrix1[i:i+5]))
#print matrix_list1

for i in range(0,len(matrix2),5):
    matrix_list2.append(list(matrix2[i:i+5]))
#print matrix_list2

for i in range(0,len(pla),5):
    pla_list.append(list(pla[i:i+5]))
#print pla_list

#查询两个密文字母位置
def find_index1(x):
    for i in range(len(matrix_list1)):
        for j in range(len(matrix_list1[i])):
            if matrix_list1[i][j] == x:
                return i,j
def find_index2(y):
    for k in range(len(matrix_list2)):
        for l in range(len(matrix_list2[k])):
            if matrix_list2[k][l] == y:
                return k,l

def gen_pla(letter):

    #两个子母中第一个字母位置
    first = find_index1(letter[0])

    #两个子母中第二个字母位置
    second = find_index2(letter[1])

    pla = ""
    pla += pla_list[first[0]][second[1]]
    pla += pla_list[second[0]][first[1]]

    return pla

def main():
    cip = "BLMIMTOWUNCBMD"
    pla = ""
    for i in range(0,len(cip),2):
        pla += gen_pla(cip[i:i+2])
    print pla

if __name__ == "__main__":
    main()

运行结果如下:

安恒杯10月月赛“四四方方一座城”解析:

题目:

分析可知:

秘钥又被加密了,Offset未知,但是我们可以遍历大小写字母的ascii码值经过异或和按位与运算之后的最大值、最小值(192,255),还有遍历enc_key的ascii码值的最大值和最小值(76,106),可以大概推算Offset的值,肯定为负数,范围可以暂时定在(-179,-86),在遍历过程中可以再做调整,由此可以遍历出正确的Offset值。

代码:

代码语言:javascript
复制
enc_key1 = "VXYjj"
key1 = ""
for Offset in range(90,150):
    for i in enc_key1:
        key1 += chr((ord(i) + Offset) ^ 0xff & 0xaf)
    print key1
    key1 = ""

结果:

经过遍历,Offset值为-149,从而推算出key值。

key1为:DBAPP

Key2为:LINKEDBYX

题目标题为“四四方方一座城”,有一个密码叫四方密码,正好是有两个秘钥,通过四个矩阵(两个秘钥矩阵,两个顺序矩阵)来加密一些信息。

对于本题中的秘钥,矩阵是这样的,如下图所示:

前两个密文字母为“XB”,解出明文为“wh”:对应矩阵如下:

根据上述解密原理,可以算出flag,利用上边的脚本,将密文和秘钥替换,运行得到flag

最后将得到的字符串进行md5加密提交即可

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档