Stanford - Cryptography I - Week 1-1 Programming Assignment
来源:互联网 发布:windows.old 1 删不掉 编辑:程序博客网 时间:2024/06/06 00:17
题注
今天我的留学生朋友伊万发给我微信,说Coursera的课程太棒了!我还想呢,这是感慨哪门课程啊。一问才知道,原来是Dan Boneh的Cryptography I又开始新的学期了。而且,他做了一些Programming Assignment,并且说从我以前的技术博客中学到了很多的东西。这我才想起来,我本来很早之间就计划把Cryptography I的Programming Assignments答案更新一遍,方便让更多的朋友们顺利地完成Cryptography I的学习。这正好是一个机会,就开始更新吧~!
在更新前,首先介绍一个Dan Boneh这个人。这个人呀,刚开始我还不知道是个什么水平的,只知道是Stanford的一个教授。结果我直博第一年阅读辅导我导师提供的三篇论文,发现竟然有两篇论文都是Dan Boneh写的,一篇发表在《Journal of Cryptography》,一篇发表在会议Asiacrypt中。要知道,这可都是密码学顶级的会议和期刊啊!随着研究的进一步发展,尤其自己是研究双线性对相关的密码学算法,才知道Dan Boneh是一个多么恐怖的人。
有兴趣的朋友可以浏览下下面的链接,来看看Dan Boneh的研究成果。
http://www.informatik.uni-trier.de/~ley/pers/hd/b/Boneh:Dan
值得一提的是,一些现在知名的密码学家,如Craig Gentry,Brent Waters, Ben Lynn等等都是Boneh的学生,特别要注意的是,现在密码学中广泛使用的Pairing Based Cryptography Library就是Ben Lynn编写并维护的。
好了,废话就说到这里,开始Week 1的Assignment吧!第一周的Assignment有两个题目,我分两个Blog来写。
问题
Many Time Pad
Let us see what goes wrong when a stream cipher key is used more than once. Below are eleven hex-encoded ciphertexts that are the result of encrypting eleven plaintexts with a stream cipher, all with the same stream cipher key. Your goal is to decrypt the last ciphertext, and submit the secret message within it as solution.
Hint: XOR the ciphertexts together, and consider what happens when a space is XORed with a character in [a-zA-Z].
ciphertext #1:
ciphertext #2:
ciphertext #3:
ciphertext #4:
ciphertext #5:
ciphertext #6:
ciphertext #7:
ciphertext #8:
ciphertext #9:
ciphertext #10:
target ciphertext (decrypt this one):
For completeness, here is the python script used to generate the ciphertexts.(it doesn't matter if you can't read this)
import sysMSGS = ( --- 11 secret messages --- )def strxor(a, b): # xor two strings of different lengths if len(a) > len(b): return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)]) else: return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])def random(size=16): return open("/dev/urandom").read(size)def encrypt(key, msg): c = strxor(key, msg) print print c.encode('hex') return cdef main(): key = random(1024) ciphertexts = [encrypt(key, msg) for msg in MSGS]
分析
这道题如果不刻意做的话,似乎是没办法写成一个程序,然后处理并等待结果的。为什么呢?因为这道题中间的几个步骤需要我们用“眼睛”来看。做出这道题,核心点就是理解hint中的提示。
首先,我们需要查阅一下space,即空格的ASCII码,以及字母[a-z]和[A-Z]的ASCII码,并寻找一下他们之间的关系。下面是整个ASCII码表,为了后面方便,我们将ASCII码用8位2进制来表示:
000000010010001101000101011001110000NULDLESP0@P·p0001SOHDC1!1AQaq0010STXDC2"2BRbr0011ETXDC3#3CScs0100EOTDC4$4DTdt0101ENQNAK%5EUeu0110ACKSYN&6FVfv0111BELETB'7GWgw1000BSCAN(8HXhx1001HTEM)9IYiy1010LFSUB*:JZjz1011VTESC+;K[k{1100FFFS,<L、l|1101CRGS-=M]m}1110SORS.>N^n~1111SIUS/?O_oDEL我们来观察一下这个码表。[A-Z]用[0x41-0x5a]表示。相应地,[a-z]用[0x61-0x7a]表示。而空格,则用0x20表示,也就是表格中的SP。空格这个表示带来了一个很巧妙的转换:如果一个大写字母与空格与或,那么结果为一个对应的小写字母;如果一个小写字母与空格与或,那么结果为一个对应的大写字母!举两个例子:
a ^ SP = 01100001 ^ 00100000 = 01000001 = A
A ^ SP = a ^ SP ^ SP = a
同时,解密过程中也用到了xor的另一个性质:对于一个数,连续与或两次任意相同的数,其结果与原数相同。用公式表示就是,对于任意的x和y:
x ^ y ^ y = x
根据提示,每一个ciphertext都是用相同的streamcipher加密的。因此,假设plaintext分别为m1、m2,那么c1 = m1 ^ k, c2 = m2 ^ k,于是c1 ^ c2= m1 ^ k ^ m2 ^ k = m1 ^ m2。这样我们就把k消去,只剩下了m1和m2。
那么,我们的解法就很显然了:随便找任意给定的m_i,m_j相与或,如果发现了有意义的英文字母,那么对应位上很可能一个是空格,另一个是英文字母。这个说起来比较绕口,我们还是举个例子:
m_1a b c d e f g hm_2 i j k l m n o我们将其用一个随机的key来加密,加密结果为c_1和c_2。我们进行与或运算,即c_1 ^ c_2,则有:
c_1 ^ c_2 = m_1 ^ key ^ m_2 ^ key = m_1 ^ m_2
m_1a b c d e f g hm_2 i j k l m n o c_1 ^ c_2AIBJCKDIEMFNGOH这样,c_1^c_2就透露了很多其他的信息。那么,怎么确定谁是空格,谁是字母呢?我们还有其他8个ciphertext嘛。重复进行这样的操作,甚至最多进行10*9/2=45次与或计算,计算所有c_i与c_j的与或结果,我们就能够恢复出大部分的信息了。最后,根据英文使用习惯,能够得到10个密文所对应的明文了。实际上,如果我们找到了某一位对应的明文,那么我们通过计算c_i ^ m_i = m_I ^ key ^ m_i = key,能够把对应的key都恢复出来,这样更能加快我们的计算速度了。
这道题我没有刻意弄出一个运行后直接得到结果的程序,在此我给出一个验证程序,验证程序中包括了Java中与或运算等这道题涉及到的Java相关使用,大家可以参考我的代码来实现自己的代码,最终解出这道题。
代码
W1Solution.java
import java.io.UnsupportedEncodingException;import java.math.BigInteger;public class W1Solution { //给定的10个ciphertext以及target ciphertext private final String string_cipher_text01 = "315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b1" + "6349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba50"; private final String string_cipher_text02 = "234c02ecbbfbafa3ed18510abd11fa724fcda2018a1a8342cf064bbde548b12b07df" + "44ba7191d9606ef4081ffde5ad46a5069d9f7f543bedb9c861bf29c7e205132eda9382b0bc2c5c4b45f919cf3a9f1cb741"; private final String string_cipher_text03 = "32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df" + "44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de812"; private final String string_cipher_text04 = "32510ba9aab2a8a4fd06414fb517b5605cc0aa0dc91a8908c2064ba8ad5ea06a0290" + "56f47a8ad3306ef5021eafe1ac01a81197847a5c68a1b78769a37bc8f4575432c198ccb4ef63590256e305cd3a9544ee41"; private final String string_cipher_text05 = "3f561ba9adb4b6ebec54424ba317b564418fac0dd35f8c08d31a1fe9e24fe56808c2" + "13f17c81d9607cee021dafe1e001b21ade877a5e68bea88d61b93ac5ee0d562e8e9582f5ef375f0a4ae20ed86e935de812"; private final String string_cipher_text06 = "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d8" + "4aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d"; private final String string_cipher_text07 = "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c9" + "09ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af513"; private final String string_cipher_text08 = "315c4eeaa8b5f8bffd11155ea506b56041c6a00c8a08854dd21a4bbde54ce56801d9" + "43ba708b8a3574f40c00fff9e00fa1439fd0654327a3bfc860b92f89ee04132ecb9298f5fd2d5e4b45e40ecc3b9d59e941"; private final String string_cipher_text09 = "271946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d5" + "13e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f404"; private final String string_cipher_text10 = "466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed395980" + "05b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d"; private final String target_text = "32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e90" + "52ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904"; //这里是猜想到的key,我在这已经给出最终key的结果 private final String guest_key = "66396e89c9dbd8cc9874352acd6395102eafce78aa7fed28a07f6bc98d29c50b69b0" + "339a19f8aa401a9c6d708f80c066c763fef0123148cdd8e802d05ba98777335daefcecd59c433a6b268b60bf4eF03C9A61"; //将每一个ciphertext转换成为BigInteger private BigInteger bigIntegerText01 = new BigInteger(string_cipher_text01,16); private BigInteger bigIntegerText02 = new BigInteger(string_cipher_text02,16); private BigInteger bigIntegerText03 = new BigInteger(string_cipher_text03,16); private BigInteger bigIntegerText04 = new BigInteger(string_cipher_text04,16); private BigInteger bigIntegerText05 = new BigInteger(string_cipher_text05,16); private BigInteger bigIntegerText06 = new BigInteger(string_cipher_text06,16); private BigInteger bigIntegerText07 = new BigInteger(string_cipher_text07,16); private BigInteger bigIntegerText08 = new BigInteger(string_cipher_text08,16); private BigInteger bigIntegerText09 = new BigInteger(string_cipher_text09,16); private BigInteger bigIntegerText10 = new BigInteger(string_cipher_text10,16); private BigInteger bigIntgerTargetText = new BigInteger(target_text,16); private BigInteger bigIntegerGuestKey = new BigInteger(guest_key,16); //计算过程如下 public void calculateAndPrint(){ try { System.out.println("Plaintext 01: " + new String(bigIntegerGuestKey.xor(bigIntegerText01).toByteArray(), "GBK")); System.out.println("Plaintext 02: " + new String(bigIntegerGuestKey.xor(bigIntegerText02).toByteArray(), "GBK")); System.out.println("Plaintext 03: " + new String(bigIntegerGuestKey.xor(bigIntegerText03).toByteArray(), "GBK")); System.out.println("Plaintext 04: " + new String(bigIntegerGuestKey.xor(bigIntegerText04).toByteArray(), "GBK")); System.out.println("Plaintext 05: " + new String(bigIntegerGuestKey.xor(bigIntegerText05).toByteArray(), "GBK")); System.out.println("Plaintext 06: " + new String(bigIntegerGuestKey.xor(bigIntegerText06).toByteArray(), "GBK")); System.out.println("Plaintext 07: " + new String(bigIntegerGuestKey.xor(bigIntegerText07).toByteArray(), "GBK")); System.out.println("Plaintext 08: " + new String(bigIntegerGuestKey.xor(bigIntegerText08).toByteArray(), "GBK")); System.out.println("Plaintext 09: " + new String(bigIntegerGuestKey.xor(bigIntegerText09).toByteArray(), "GBK")); System.out.println("Plaintext 10: " + new String(bigIntegerGuestKey.xor(bigIntegerText10).toByteArray(), "GBK")); System.out.println("Target Text : " + new String(bigIntegerGuestKey.xor(bigIntgerTargetText).toByteArray(), "GBK")); }catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public static void main(String[] args){ new W1Solution().calculateAndPrint(); }}
答案
程序运行后的截图如图。
因此我们可以得到正确的Target Text: The secret message is: when using a stream cipher, never use the key more than once
- Stanford - Cryptography I - Week 1-1 Programming Assignment
- Stanford - Cryptography I - Week 1-2 Programming Assignment
- Stanford - Cryptography I - Week 3 Programming Assignment
- Cryptography I, Week 1: Stream Ciphers
- [Stanford Cryptography I] Week1
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 1 Assignment: number of inversions
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 2 Assignment: QuickSort
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 3 Assignment: Contraction
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 4 Assignment: strongly connected component
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 5 Assignment: Dijkstra
- Stanford - Algorithms: Design and Analysis, Part 1 - Week 6 Assignment: hash table and heap
- Stanford - Algorithms: Design and Analysis, Part 2 - Week 1 Assignment: Greedy and Prim
- Machine Learning Stanford (week 1)
- R Programming Assignment 1
- Programming Assignment 1: Percolation
- Stanford 算法入门 week 2 Assignment QuickSort
- Stanford 算法入门 week 3 Assignment
- Programming Assignment 1: Percolation代码
- BLL 、DAL、MODEL三层架构+UI
- 浅谈数据质量管理
- 杂记
- uva 11627
- 新浪微博Oauth2.0授权 获取Access Token以及API的使用
- Stanford - Cryptography I - Week 1-1 Programming Assignment
- 新闻去重算法的设计和实现
- service--取得运行的Activity
- Set Off
- php有点进入状态了
- 面试题:const、static、sizeof
- LaTeX的BibTeX引用网页的办法
- Linux环境下段错误的产生原因及调试方法小结
- Probably ResourceManager is not defined in the View【ASP.NET MVC4+EXT.NET配置常见错误】