题目源码:
#加密代码
def encrypt(plainText):
space = 10
cipherText = ""
for i in range(len(plainText)):
if i + space < len(plainText) - 1:
cipherText += chr(ord(plainText[i]) ^ ord(plainText[i + space]))
else:
cipherText += chr(ord(plainText[i]) ^ ord(plainText[space]))
if ord(plainText[i]) % 2 == 0:
space += 1
else:
space -= 1
return cipherText
# 密码
# 15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206
加密原理是明文自身每个字节依次与自身的某一个字节异或,与谁异或由space决定
第一步要做的就是把space的变化情况爆破出来
space初始为10,后续根据明文的ascii值是否为偶数来决定space加一还是减一
明文字符的ascii值可以根据其二进制的最后一位判断,为0则为偶数,1则为奇数
首先爆破出明文字符串中每个字符的二进制的最后一位
明文和密文长度一样,为28个字符,由每个字符的最后一位组成的字符串也是28,二进制最后一位要么是0要么是1,那么这个由明文每个字符二进制最后一位组成的字符串一共有2的28次方的可能性,爆破:
c='15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206'
c=bytes.fromhex(c)
def crackit():
'''
暴力求出每个明文字符的最后一位
:return: 每个明文字符最后一位组成的字符串
'''
for x in range(1<<28):
temp=bin(x)[2:].zfill(28)
space = 10
flag=0
for i in range(len(temp)):
if i + space < len(temp) - 1:
tempx= int(temp[i]) ^ int(temp[i + space])
else:
tempx= int(temp[i]) ^ int(temp[space])
if tempx!=(c[i]%2):
flag=1
break
elif int(temp[i]) % 2 == 0:
space += 1
else:
space -= 1
if flag!=1:
print(temp)
break
#temp='1010011010010101111111101001'
爆破出tmp后,我们可以根据tmp也就是每个明文字符ascii的奇偶性来找到密文字符是由明文对应字符与明文的哪个位置上的字符异或得来的
也就是爆出来space,然后求出来space或者space+i是多少
temp='1010011010010101111111101001'
def crackit_2():
'''
解出每个方程中的明文字符的序号.
:return: 每个方程中的明文字符的序号组成的列表.
'''
space = 10
g=[]
for i in range(len(temp)):
if i + space < len(temp) - 1:
g.append((i,i+space))
else:
g.append((i,space))
if int(temp[i]) % 2 == 0:
space += 1
else:
space -= 1
return g
最后根据这个列表来还原密文,简单的异或
#加密代码
def encrypt(plainText):
space = 10
cipherText = ""
for i in range(len(plainText)):
if i + space < len(plainText) - 1:
cipherText += chr(ord(plainText[i]) ^ ord(plainText[i + space]))
else:
cipherText += chr(ord(plainText[i]) ^ ord(plainText[space]))
if ord(plainText[i]) % 2 == 0:
space += 1
else:
space -= 1
return cipherText
# 密码
# 15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206
c='15120d1a0a0810010a031d3e31000d1d170d173b0d173b0c07060206'
c=bytes.fromhex(c)
def crackit():
'''
暴力求出每个明文字符的最后一位
:return: 每个明文字符最后一位组成的字符串
'''
for x in range(1<<28):
temp=bin(x)[2:].zfill(28)
space = 10
flag=0
for i in range(len(temp)):
if i + space < len(temp) - 1:
tempx= int(temp[i]) ^ int(temp[i + space])
else:
tempx= int(temp[i]) ^ int(temp[space])
if tempx!=(c[i]%2):
flag=1
break
elif int(temp[i]) % 2 == 0:
space += 1
else:
space -= 1
if flag!=1:
print(temp)
break
temp='1010011010010101111111101001'
def crackit_2():
'''
解出每个方程中的明文字符的序号.
:return: 每个方程中的明文字符的序号组成的列表.
'''
space = 10
g=[]
for i in range(len(temp)):
if i + space < len(temp) - 1:
g.append((i,i+space))
else:
g.append((i,space))
if int(temp[i]) % 2 == 0:
space += 1
else:
space -= 1
return g
def solve():
g=crackit_2()
plain=['a','f','c','t','f','{']+[-1]*22
while -1 in plain:
for i in range(28):
if plain[g[i][0]]!=-1:
plain[g[i][1]]=chr(ord(plain[g[i][0]])^c[i])
elif plain[g[i][1]]!=-1:
plain[g[i][0]]=chr(ord(plain[g[i][1]])^c[i])
for i in plain:
print(i,end='')
print('\n')
print(crackit_2())