题目如下:
Vigenere3d
----- Vigenere3d.py
import sys
def _l(idx, s):
return s[idx:] + s[:idx]
def main(p, k1, k2):
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
i1 = 0
i2 = 0
c = ""
for a in p:
c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return c
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
-----
$ python Vigenere3d.py SECCON{**************************} **************
POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9
首先题目生成一个三维数组的密码本,就好比谍战片的流密码本;
加密的过程:
- (1):首先查找在s中的位置,作为数组的第一维
- (2):取 第二参数(子字符串)一位,作为数组的第二维,依次相模。
- (3):取第三个参数的一位,作为数组的第三维。(这里和上一步骤一样,但是取的方法是从后往前取值)
for a in p:
c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return c
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
这里有个细节说一下:
我一直不明白一个问题,这个题好像对解密的key值的位数,并没有做说明。
$ python Vigenere3d.py SECCON{**************************} **************
POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9
从这里看到第二个参数的位数为14,固推断key位数为14
解密过程:
$ python Vigenere3d.py SECCON{**************************} **************
POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9
- 1: 对已知部分“SECCON{”进行加密,加密的所使密钥依次使用s串中字符。
- 2:加密后的字符串依次和题目中所给出的的字符串 ciphertext进行匹配;匹配成功,将加密使用的字符写入key中。
res = encrypt(known_prefix, key, key[::-1])
if res[pos] == ciphertex[pos]:
final_key[pos] = c
final_key[13 - pos] = c
print "".join(final_key)
- 3: 参数2、参数3也就是加密所使用的k1、k2.互为倒数。
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
设置一个14位的字符串,写入时。使用如下方式即可:(在第一位 写一个,在最后一位写一个)
partial_candidate_key[pos] = c
partial_candidate_key[13 - pos] = c
得到解密k,及时解密。
完整脚本如下:
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
def _l(idx, s):
return s[idx:] + s[:idx]
def decrypt(ct, k1, k2):
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
t = [[_l((i + j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
i1 = 0
i2 = 0
decrypted = ""
for a in ct:
for c in s:
if t[s.find(c)][s.find(k1[i1])][s.find(k2[i2])] == a:
decrypted += c
break
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return decrypted
def encrypt(p, k1, k2):
t = [[_l((i + j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
i1 = 0
i2 = 0
c = ""
for a in p:
c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return c
def recover_key(known_prefix, ciphertex):
final_key = ['*'] * 14
for pos in range(7):
for c in s:
partial_candidate_key = ['*'] * 14
partial_candidate_key[pos] = c
partial_candidate_key[13 - pos] = c
key = "".join(partial_candidate_key)
res = encrypt(known_prefix, key, key[::-1])
if res[pos] == ciphertex[pos]:
final_key[pos] = c
final_key[13 - pos] = c
print "".join(final_key)
return "".join(final_key)
def main():
ciphertext = "POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9"
key = recover_key("SECCON{", ciphertext)
flag = decrypt(ciphertext, key, key[::-1])
print(flag)
main()