http://www.wechall.net/challenge/training/crypto/transposition1/index.php
oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wn aambsgrsbm.s
这题考的是置换密码。古典密码学的问题搞清楚概念比较重要,一般容易混淆移位密码、置换密码和代换密码。
这个学期上了计算机密码学,虽然什么都没有从老师口中学到,但是知道考试强迫我自学了很多很多很多……而这门课居然还是我本学期最高分的一门课,真是太菜了。回到正题。
置换只不过是一个简单的换位,每个置换都可以用一个置换矩阵Ek来表示。每个置换都有一个与之对应的逆置换Dk。置换密码的特点是仅有一个发送方和接受方知道的加密置换(用于加密)及对应的逆置换(用于解密)。它是对明文L长字母组中的字母位置进行重新排列,而每个字母本身并不改变。
去百度百科抄了一段下来。
要注意的重点有两点:
- 置换就是换个位置而已。
- 换位置不太可能全局换,因为这样不能用于任意长明文的加密。一般置换都有一个分段长度。
好了,其实第2点就是解密的关键。因为置换密码必然要成段才能参与置换,因此密文的长度必然是分段长度的整数倍。
数一数,密文148个字符(记得要算上空格)。148=2 * 2 * 37
好了那你觉得段长是2呢还是4呢还是37呢还是更大呢?
显然,一眼就能看出4大概是对的。
下面就剩下写代码了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
""" oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wn aambsgrsbm.s 148=2 * 2 * 37 = 4 * 37 """ def main(): trans=[1,0,3,2] ciphertext="oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wn aambsgrsbm.s" group=[ciphertext[4*x:4*x+4] for x in range(len(ciphertext)//4)] plaintext=[transposition(cipher,trans) for cipher in group] print("".join(plaintext)) def transposition(seg, trans): """ len(seg) should be equal to len(trans). trans: e.g. [1,3,2,4], then "ABCD"-->"ACBD" """ assert len(seg)==len(trans) trans_seg=[0]*len(seg) for i in range(len(seg)): trans_seg[trans[i]]=seg[i] return "".join(trans_seg) if __name__=="__main__": main() |
结果如下:
Wonderful. You can read the message way better when the letters are in correct order. I think you would like to see your password now: naabmgssrmbs.