四方密碼

原理&簡介

四方密碼是一種對稱式加密法,由法國人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編寫加密腳本如下:

#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編寫解密腳本如下:

#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值。

代碼:

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加密提交即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章