当时做题的时候得到的式子:
(m[0] & key) % 2 == ?
(m[1] & key) % 2 == *
其中?和 * 很明显,不是0就是1啊!所以不妨换一种思路,如果我们把m和key都转化为二进制数,会发生什么!
M表示m展开后的矩阵,K表示key展开之后的向量,C为cipher.txt转成的01向量,即有:MK = C
矩阵乘法!二进制下的!也就是说,在有限域GF(2)中,有已知的矩阵M和密文C,要求密钥K!
答案是:高斯消元
题解地址:
https://www.xctf.org.cn/library/details/2ff21f569a791e21cbd6ce0d4675a9de5ec2373a/
https://findneo.tech/180527suctf/#Magic
第二篇wp的写法姿势特别好:(论算法的重要性)
翻译一下这行代码:
read_to_int_array = lambda x:[map(int,list(bin(int(line,16))[2:].zfill(dim))) for line in open(x).readlines()]
举例:
s = "e6aec69625130b77330f5b5abaf4155c862b625dce1bbfbd3fb54ea3d914b91"
print int(s,16)
print bin(int(s,16))
print bin(int(s,16))[2:]
print bin(int(s,16))[2:].zfill(dim)
print list(bin(int(s,16))[2:].zfill(dim))
print map(int,list(bin(int(s,16))[2:].zfill(dim)))
结果是这样的:
6521297322318485135397962758917330134336256120928714851050733785157196663697
0b111001101010111011000110100101100010010100010011000010110111011100110011000011110101101101011010101110101111010000010101010111001000011000101011011000100101110111001110000110111011111110111101001111111011010101001110101000111101100100010100101110010001
111001101010111011000110100101100010010100010011000010110111011100110011000011110101101101011010101110101111010000010101010111001000011000101011011000100101110111001110000110111011111110111101001111111011010101001110101000111101100100010100101110010001
0000111001101010111011000110100101100010010100010011000010110111011100110011000011110101101101011010101110101111010000010101010111001000011000101011011000100101110111001110000110111011111110111101001111111011010101001110101000111101100100010100101110010001
['0', '0', '0', '0', '1', '1', '1', '0', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '1', '0', '1', '1', '0', '0', '0', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '1', '0', '1', '0', '0', '0', '1', '0', '0', '1', '1', '0', '0', '0', '0', '1', '0', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '0', '1', '1', '0', '0', '1', '1', '0', '0', '0', '0', '1', '1', '1', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1', '1', '0', '1', '0', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0', '0', '1', '0', '1', '0', '1', '0', '1', '0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '0', '1', '1', '0', '0', '0', '1', '0', '1', '0', '1', '1', '0', '1', '1', '0', '0', '0', '1', '0', '0', '1', '0', '1', '1', '1', '0', '1', '1', '1', '0', '0', '1', '1', '1', '0', '0', '0', '0', '1', '1', '0', '1', '1', '1', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '1', '0', '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '0', '1', '1', '0', '1', '0', '1', '0', '1', '0', '0', '1', '1', '1', '0', '1', '0', '1', '0', '0', '0', '1', '1', '1', '1', '0', '1', '1', '0', '0', '1', '0', '0', '0', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '0', '0', '1', '0', '0', '0', '1']
[0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1]
转为10进制,再转为二进制,去掉前面的0b,然后补全256位,再拆开成256个0或1,拼到另外一个list中
接下来就是处理高斯消元了
dim = 256
read_to_int_array = lambda x:[map(int,list(bin(int(line,16))[2:].zfill(dim))) for line in open(x).readlines()]
cipher = read_to_int_array('cipher.txt')[0]
magic = read_to_int_array('magic.txt')
'''
s = "e6aec69625130b77330f5b5abaf4155c862b625dce1bbfbd3fb54ea3d914b91"
print int(s,16)
print bin(int(s,16))
print bin(int(s,16))[2:]
print bin(int(s,16))[2:].zfill(dim)
print list(bin(int(s,16))[2:].zfill(dim))
print map(int,list(bin(int(s,16))[2:].zfill(dim)))
'''
for j in range(dim):
for i in range(j,dim):
if magic[i][j] == 1:
magic[i],magic[j] = magic[j],magic[i]
cipher[i],cipher[j] = cipher[j],cipher[i]
break
for i in range(dim):
if magic[i][j] == 1 and i != j:
for k in range(dim):
magic[i][k] ^= magic[j][k]
cipher[i] ^= cipher[j]
print "flag{%s}"%hex(int(''.join(map(str,cipher)),2))[2:-1].decode('hex')
就可以看到flag了咯!~