在之前吧我们讲过了希尔密码的理论,接下来我们讲实战。
abcde…x y z
12345…242526
有的题a是从0开始的。
一、条件
首先,我们打ctf一般会给我们两个条件:
1.密文
2.矩阵(也叫解密矩阵)
二、目的
1、根据矩阵,求出逆矩阵。
2、逆矩阵与密文对应的矩阵相乘。(一定要注意写密文矩阵的顺序)
3、得到矩阵b,每一个数与26相余。
4.得到的余数转ascii
三、实战
例题一、
密文:dloguszijluswogany
矩阵:
1 2
0 1
1、逆矩阵:
from numpy import *
a1=mat([[1,2],[0,1]])
print(a1)
a2=a1.I
print(a2)
[[ 1. -2.]
[ 0. 1.]]
2、密文转化:
d l o g u s z i j l u s w o g a n y
4 12 15 7 21 19 26 9 10 12 21 19 23 15 7 1 14 25
3、逆矩阵与密文矩阵相乘
from numpy import *
a=mat([[1,-2],[0,1]])
b=mat([[4,15,21,26,10,21,23,7,14],[12,7,19,9,12,19,15,1,25]])
c=a*b
print(c)
[[-20 1 -17 8 -14 -17 -7 5 -36]
[ 12 7 19 9 12 19 15 1 25]]
4、矩阵mod26
负数直接加上二十六的对数。mod26。
例题二、
1、同理求逆矩阵:
[[ 1. -1.]
[-2. 3.]]
2、密文转化
密文:m t t p j b p e x f d z c e g t d z e a n u t z
明文:13 20 20 16 10 2 16 5 24 6 4 26 3 5 7 20 4 26 5 1 14 21 20 26
3、mod26
例题三、
密文:22,09,00,12,03,01,10,03,04,08,01,17 (wjamdbkdeibr)
矩阵:
1 2 3
4 5 6
7 8 10
1、转可逆矩阵
我们可以看到转化可逆矩阵,竟然得到了分数。出现分数项则 *最小公倍数(27,|D|) |D|为行列式的值
a3=mat([[1,2,3],[4,5,6],[7,8,10]])
print(a3)
a4=a3.I
print(a4)
求行列式:
def MatrixGetDet(M):
length = len(M)
if length == 2:
return M[0][0]*M[1][1] - M[0][1]*M[1][0]
import itertools
# sum positive
positive = 0
indexer1 = itertools.cycle(range(length))
indexer2 = itertools.cycle(range(length))
for index in range(length):
indexer1.next()
_tmp = 1
for index in range(length):
index1 = indexer1.next()
index2 = indexer2.next()
_tmp *= M[index1][index2]
positive += _tmp
# sum negative
negative = 0
indexer1 = itertools.cycle(range(length))
indexer2 = itertools.cycle(range(length)[::-1])
for index in range(length):
indexer1.next()
_tmp = 1
for index in range(length):
index1 = indexer1.next()
index2 = indexer2.next()
_tmp *= M[index1][index2]
negative += _tmp
# return
return positive - negative
matrix1 = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 0],
]
matrix2 = [
[1, 2],
[4, 5]
]
matrix3 = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 10],
]
matrix4 = [
[1,2,3,4,5],
[2,3,4,5,1],
[3,4,5,1,2],
[4,5,1,2,3],
[5,1,2,3,4]
]
print MatrixGetDet(matrix1)
print MatrixGetDet(matrix2)
print MatrixGetDet(matrix3)
print MatrixGetDet(matrix4)
|1 2 3 |
|4 5 6 | 行列式的值为 -3
|7 8 10|
所以最小公倍数为27,矩阵 * 27:
-18 -36 27
-18 99-54
27 -54 27
解密矩阵为(就是上面的矩阵,加上26的倍数)
8 16 27
8 99 24
27 24 27
2、密文对应的矩阵
[22,12,10,8 ]
[9,3,3,1]
[0,1,4,7] 其实这个矩阵是错误的。因为我使用python算矩阵的成绩的时候是错误的。
正确的矩阵为:
[22,9,0] [8,16,27]
[12,3,1] * [8,99,24]
[10,3,4] [27,24,27]
[8,1,17]
最终结果:
from numpy import *
dis={1:'a',2:'b',3:'c',4:'d',5:'e',6:'f',7:'g',8:'h',9:'i',10:'j',11:'k',12:'l',13:'m',14:'n',15:'o',16:'p',17:'q',18:'r',19:'s',20:'t',21:'u',22:'v',23:'w',24:'x',25:'y',26:'z'}
a=mat([[1,-2],[0,1]])
b=mat([[4,15,21,26,10,21,23,7,14],[12,7,19,9,12,19,15,1,25]])
c=a*b
print(c)
f=mat([[8,16,27],[8,99,24],[27,24,27]])
e=mat([[22,9,0],[12,03,01],[10,03,04],[8,1,17]])
g=e*f
print(g)
h=([[248,1243,810],
[147,513,423],
[212,553,450],
[531,635,699]])
for i in range(4):
for j in range(3):
k=(h[i][j])%26+1
print(k)
l=dis[k]
print(l)
最终得到flag。
总结:
1.在转换逆矩阵的时候,如果出现了分数或者小数。我们需要讲逆矩阵乘以27和d(给我们的矩阵的行列式)的最小公倍数。
2.再就是我们如何处理密文,列出正确的矩阵。比如我在最后一道题就在矩阵出了问题。他是依据给我们的矩阵的行数。以行数为一组。以此填到每一列。比如:行数为3。密文为:21 22 34 45 56 6 4,则矩阵为:
21 45
22 56
34 6