Coursera Dan Boneh Week 1 Program Assignment Many Time Pad
PA1 option
Write a program that allows you to “crack” ciphertexts generated using a Vigenere-like cipher, where byte-wise XOR is used instead of addition modulo 26.
http://www.cryptopals.com/sets/1
(1) Convert hex to base64
(2) Fixed XOR
(3) Single-byte XOR cipher
(4) Detect single-character XOR
(5) Implement repeating-key XOR
(6) Break repeating-key XOR
MTC3 Cracking SHA1-Hashed Passwords https://www.mysterytwisterc3.org/en/challenges/level-2/cracking-sh a1-hashed-passwords
题目描述(清楚描述题目中文,写出自己的理解,请勿复制原题目)
1.Coursera Dan Boneh Week 1 Program Assignment Many Time Pad
题目大意:有11个同一异或加密流密码密钥加密的密文,尝试解密最后一个密文。
思路:由于使用了同一个密钥异或加密10个明文,导致生成的密文互相异或会得到部分信息,比如空格和小写字母异或将得到大写字母,可以根据空格的位置猜测部分信息
2.PA1 option
题目大意:编写一个程序,破解使用维吉尼亚类似密码生成的密文,不过把加密方法变为了异或。
思路:由于密钥是两个4位16进制的字符串,并且加密方式位异或,可以通过遍历密钥异或密文判断有效可见明文的数量来确实密钥,得到密钥就可以破解密文。
3. http://www.cryptopals.com/sets/1
此url上的前六个问题
1)Convert hex to base64
题目大意:把16进制字符串转化为base64编码
思路:调用python函数即可转化编码
2)Fixed XOR
题目大意: 把两个等长的字符串按位进行异或
思路: 一个字符单独异或最后转化为新字符串
3)Single-byte XOR cipher
题目大意:单个字符进行异或加密。找到密钥,解密消息。
思路: 遍历密钥和密文每一位进行解密操作,破译出的可见明文越多那么越可能是密钥
4)Detect single-character XOR
题目大意: 单个字符串对txt中的一条明文进行异或加密
思路: 同第三题思路不过是要遍历整个txt
5)Implement repeating-key XOR
题目大意: 使用ICE三个字符类似维吉尼亚的分组加密字符串破译
思路: 按要求分组加密即可
6)Break repeating-key XOR
题目大意: 使用平均汉明距离破解密文,加密方法为分组异或
思路: 在不同密钥长度将密文的txt分组,取四个分组计算平均汉明距离,使用最低的几个密钥长度,按类似第三题的思路遍历找到密钥
4.MTC3CrackingSHA1-HashedPasswords
https://www.mysterytwisterc3.org/en/challenges/level-2/cracking-sh a1-hashed-passwords
以上网址的题目
题目大意:更具键盘的按键与密码输入下的限制条件和对应的sha1值判断输入的password
思路:题目给了sha1值和限制条件,遍历可能的密钥和sha1对照即可
import sys
from operator import methodcaller
import re
def main():
cypherTexts = []
# cyphertext 1 (0)
cypherTexts.append(
"315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e")
# cyphertext 2 (1)
cypherTexts.append(
"234c02ecbbfbafa3ed18510abd11fa724fcda2018a1a8342cf064bbde548b12b07df44ba7191d9606ef4081ffde5ad46a5069d9f7f543bedb9c861bf29c7e205132eda9382b0bc2c5c4b45f919cf3a9f1cb74151f6d551f4480c82b2cb24cc5b028aa76eb7b4ab24171ab3cdadb8356f")
# cyphertext 3 (2)
cypherTexts.append(
"32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de81230b59b7afb5f41afa8d661cb")
# cyphertext 4 (3)
cypherTexts.append(
"32510ba9aab2a8a4fd06414fb517b5605cc0aa0dc91a8908c2064ba8ad5ea06a029056f47a8ad3306ef5021eafe1ac01a81197847a5c68a1b78769a37bc8f4575432c198ccb4ef63590256e305cd3a9544ee4160ead45aef520489e7da7d835402bca670bda8eb775200b8dabbba246b130f040d8ec6447e2c767f3d30ed81ea2e4c1404e1315a1010e7229be6636aaa")
# cyphertext 5 (4)
cypherTexts.append(
"3f561ba9adb4b6ebec54424ba317b564418fac0dd35f8c08d31a1fe9e24fe56808c213f17c81d9607cee021dafe1e001b21ade877a5e68bea88d61b93ac5ee0d562e8e9582f5ef375f0a4ae20ed86e935de81230b59b73fb4302cd95d770c65b40aaa065f2a5e33a5a0bb5dcaba43722130f042f8ec85b7c2070")
# cyphertext 6 (5)
cypherTexts.append(
"32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d84aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d79eccf52ff111284b4cc61d11902aebc66f2b2e436434eacc0aba938220b084800c2ca4e693522643573b2c4ce35050b0cf774201f0fe52ac9f26d71b6cf61a711cc229f77ace7aa88a2f19983122b11be87a59c355d25f8e4")
# cyphertext 7 (6)
cypherTexts.append(
"32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce")
# cyphertext 8 (7)
cypherTexts.append(
"315c4eeaa8b5f8bffd11155ea506b56041c6a00c8a08854dd21a4bbde54ce56801d943ba708b8a3574f40c00fff9e00fa1439fd0654327a3bfc860b92f89ee04132ecb9298f5fd2d5e4b45e40ecc3b9d59e9417df7c95bba410e9aa2ca24c5474da2f276baa3ac325918b2daada43d6712150441c2e04f6565517f317da9d3")
# cyphertext 9 (8)
cypherTexts.append(
"271946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027")
# cyphertext 10 (9)
cypherTexts.append(
"466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83")
# cyphertext target (10)
cypherTexts.append(
"32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904")
# convert all to ASCII
cypherTextsDecoded = map(methodcaller("decode", "hex"), cypherTexts)
# chose two to XOR
crib = "There are two types of cyptography: one that allows the Government to use brute force to break the code, and one that requires the Government to use brute force to break you"
xorTextNum1 = 6
xorTextNum2 = 10
# /end interatcive
xoredText = strxor(cypherTextsDecoded[xorTextNum1], cypherTextsDecoded[xorTextNum2])
# loop all individual positions of the XOR-ed crypto (plain) text
textLength = len(xoredText)
for i in range(textLength):
# XOR the substring with the crib
substrXoredText = xoredText[i:]
cribDraggedText = strxor(substrXoredText, crib)
# do an estimated guess wether the text is readable, if so print the guess (in place)
# if(isreadable(cribDraggedText)):
# printCodePos(i, cribDraggedText, textLength, '.')
key = strxor(cypherTextsDecoded[xorTextNum1], crib)
print "Decrypt all messages using the key:"
for j, cypher in enumerate(cypherTextsDecoded):
print "[%d] %s" % (j, strxor(cypher, key))
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 isreadable(str): # check readability (allow only alphanumeric chars and some punctiation)
return bool(re.search('^[a-zA-Z0-9\., \'\"\-_\:\(\)]+$', str))
def printCodePos(i, code, maxLen, filler): # output the guess in place of the message
prefix = filler * i
ln = len(code)
postfix = filler * (maxLen - i - ln)
print("%s%s%s" % (prefix, code, postfix))
main()
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:00
"""
#pa1 weijiniya like fprintf(fpOut, "%02X", ch ^ key[i % KEY_LENGTH]); // ^ is logical XOR
def findindexkey(subarr): # 该函数可以找出将密文subarr解密成可见字符的所有可能值
visiable_chars = [] # 可见字符
for x in range(32, 126):
visiable_chars.append(chr(x))
# print(vi)
test_keys = [] # 用于测试密钥
ans_keys = [] # 用于结果的返回
for x in range(0x00, 0xFF): # 枚举密钥里所有的值
test_keys.append(x)
ans_keys.append(x)
for i in test_keys: # 对于0x00~0xFF里的每一个数i和subarr里的每个值s异或
for s in subarr:
if chr(s ^ i) not in visiable_chars: # 用i解密s,如果解密后明文不是可见字符,说明i不是密钥
ans_keys.remove(i) # 去掉ans_keys里测试失败的密钥
break
# print(ans_keys)
return ans_keys
strmi = 'F96DE8C227A259C87EE1DA2AED57C93FE5DA36ED4EC87EF2C63AAE5B9A7EFFD673BE4ACF7BE8923C\
AB1ECE7AF2DA3DA44FCF7AE29235A24C963FF0DF3CA3599A70E5DA36BF1ECE77F8DC34BE129A6CF4D126BF\
5B9A7CFEDF3EB850D37CF0C63AA2509A76FF9227A55B9A6FE3D720A850D97AB1DD35ED5FCE6BF0D138A84C\
C931B1F121B44ECE70F6C032BD56C33FF9D320ED5CDF7AFF9226BE5BDE3FF7DD21ED56CF71F5C036A94D96\
3FF8D473A351CE3FE5DA3CB84DDB71F5C17FED51DC3FE8D732BF4D963FF3C727ED4AC87EF5DB27A451D47E\
FD9230BF47CA6BFEC12ABE4ADF72E29224A84CDF3FF5D720A459D47AF59232A35A9A7AE7D33FB85FCE7AF5\
923AA31EDB3FF7D33ABF52C33FF0D673A551D93FFCD33DA35BC831B1F43CBF1EDF67F0DF23A15B963FE5DA\
36ED68D378F4DC36BF5B9A7AFFD121B44ECE76FEDC73BE5DD27AFCD773BA5FC93FE5DA3CB859D26BB1C63C\
ED5CDF3FE2D730B84CDF3FF7DD21ED5ADF7CF0D636BE1EDB79E5D721ED57CE3FE6D320ED57D469F4DC27A8\
5A963FF3C727ED49DF3FFFDD24ED55D470E69E73AC50DE3FE5DA3ABE1EDF67F4C030A44DDF3FF5D73EA250\
C96BE3D327A84D963FE5DA32B91ED36BB1D132A31ED87AB1D021A255DF71B1C436BF479A7AF0C13AA14794'
arr = [] # 密文,每个元素为字符的ascii码
for x in range(0, len(strmi), 2):
arr.append(int(strmi[x:2 + x], 16))
for keylen in range(1, 14): # 枚举密钥的长度1~14
for index in range(0, keylen): # 对密钥里的第index个进行测试
subarr = arr[index::keylen] # 每隔keylen长度提取密文的内容,提取出来的内容都被密文的第index个加密
ans_keys = findindexkey(subarr) # 找出密钥中第index个的可能的值
print('keylen=', keylen, 'index=', index, 'keys=', ans_keys)
if ans_keys: # 如果密钥第index个有可能存在,尝试用密钥的index个去解密文
ch = []
for x in ans_keys:
ch.append(chr(x ^ subarr[0]))
print(ch)
# 运行到这里,观察输出可以发现,密钥长度为7时有解
print('###############')
import string
def findindexkey2(subarr): # 再造一个函数筛选密钥
test_chars = string.ascii_letters + string.digits + ',' + '.' + ' ' # 将检查的字符改为英文+数字+逗号+句号+空格
# print(test_chars)
test_keys = [] # 用于测试密钥
ans_keys = [] # 用于结果的返回
for x in range(0x00, 0xFF): # 枚举密钥里所有的值
test_keys.append(x)
ans_keys.append(x)
for i in test_keys: # 对于0x00~0xFF里的每一个数i和substr里的每个值s异或
for s in subarr:
if chr(s ^ i) not in test_chars: # 用i解密s,如果解密后不是英文、数字、逗号、句号、空格,说明i不是密钥
ans_keys.remove(i) # 去掉ans_keys里测试失败的密钥
break
# print(ans_keys)
return ans_keys
vigenerekeys = [] # 维基尼尔密码的密钥
for index in range(0, 7): # 已经知道密钥长度是7
subarr = arr[index::7]
vigenerekeys.append(findindexkey2(subarr))
print(vigenerekeys) # 输出的是[[186], [31], [145], [178], [83], [205], [62]].
print("#########")
ming = ''
for i in range(0, len(arr)):
ming = ming + chr(arr[i] ^ vigenerekeys[i % 7][0])
print(ming)
1
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:01
"""
import base64
def hex_to_base64(hexString):
return base64.b64encode(hexString.decode('hex'))
string="49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
print (hex_to_base64(string))
2
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:08
"""
import string
import re
def xor_strings(xs,ys):
return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys))
if __name__ == '__main__':
string1='1c0111001f010100061a024b53535009181c'
string2='686974207468652062756c6c277320657965'
hex_string1=string1.encode('utf-8').decode('hex') #转化为utf-8 异或
hex_string2=string2.encode('utf-8').decode('hex')
result=xor_strings(hex_string1,hex_string2).encode('hex') #hex输出
print (result)
3
#coding=utf-8
import re
str="1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
score=0#max
for i in range(0,129):
tmp=[]
for j in re.findall(".{2}",str):#任意两个字符的字符串
tmp += chr(i^int(j,16))
tmpstr = "".join(tmp)
num=0
for j in range(0,len(tmpstr)):
if tmpstr[j]>='a'and tmpstr[j]<='z':#or tmpstr[j]>='A'and tmpstr[j]<='Z':
num+=1
if num>score:
#print tmpstr
score=num#用于更新用
ansstr=tmpstr
key=chr(i)
print key
print ansstr
4
#coding=utf-8
import re
#with open("ex4.txt") as fp:
#wenben=[i for i in open("ex4.txt").readlines()]
wenben=[]
for i in open("4.txt","r").readlines():
wenben+=[i.replace("\n","")] #序列相加 #同第三题
score=0
for k in wenben:
for i in range(0,129):
tmp=[]
for j in re.findall(".{2}",k):#任意两个字符的字符串
tmp += chr(i^int(j,16))
tmpstr = "".join(tmp)
num=0
num=len(re.findall(r'[a-zA-Z ]',tmpstr))#一定注意不要落下空格
if num>score:
score=num#用于更新用
ansstr=tmpstr
c=k
key=chr(i)
print c
print key
print ansstr
5
# -*- coding: utf-8 -*-
def xor_repeat_key(key,string):
key_len=len(key)
result=''
str_result=''
for index,ch in enumerate(string):
n=index%key_len#一组组加密
b=chr(ord(key[n])^ord(ch))
str_result+=b
return str_result
def main():
string1='Burning \'em, if you ain\'t quick and nimble\nI go crazy when I hear a cymbal'
key='ICE'
print xor_repeat_key(key,string1).encode('hex')
if __name__ == '__main__':
main()
6
#coding:utf-8
import re
import base64
with open("6.txt","r") as fp:
wenben=[base64.b64decode(i) for i in fp.readlines()]
wenben="".join(wenben)
def english_test(sentence):#字母频率
score = 0
freqs = {
'a': 0.0651738, 'b': 0.0124248, 'c': 0.0217339,
'd': 0.0349835, 'e': 0.1041442, 'f': 0.0197881,
'g': 0.0158610, 'h': 0.0492888, 'i': 0.0558094,
'j': 0.0009033, 'k': 0.0050529, 'l': 0.0331490,
'm': 0.0202124, 'n': 0.0564513, 'o': 0.0596302,
'p': 0.0137645, 'q': 0.0008606, 'r': 0.0497563,
's': 0.0515760, 't': 0.0729357, 'u': 0.0225134,
'v': 0.0082903, 'w': 0.0171272, 'x': 0.0013692,
'y': 0.0145984, 'z': 0.0007836, ' ': 0.1918182}
for x in sentence.lower():
if x in freqs:
score += freqs[x]
return score
def hanming(x,y):
num=0
for i in range(0,len(x)):
t=ord(x[i])^ord(y[i])
while t:
if t&1 : num+=1
t>>=1
return num
def thechar(st1):
score = 0
for i in range(0, 255):
tmp = []
for j in range(0,len(st1)): # 任意两个字符的字符串
tmp += chr(i ^ int(st1[j],16))
tmpstr = "".join(tmp)
#num=len(re.findall(r'[a-zA-Z ,\.;?!:]',tmpstr)) #'[a-zA-Z ,\.?!:;]'
num=english_test(tmpstr)
if num > score:
score = num # 用于更新用
key = chr(i)
#print key,score
return key
ans = []
for i in range(1,41):
str1=[]
str2=[]
str3=[]
str4=[]
for j in range(0,i): str1+=[wenben[j]]
for j in range(i,2*i): str2+=[wenben[j]]
for j in range(2*i,3*i): str3+=[wenben[j]]
for j in range(3*i,4*i): str4+=[wenben[j]]
str1="".join(str1)
str2="".join(str2)
str3="".join(str3)
str4="".join(str4)
x1=float(hanming(str1,str2))/i
x2=float(hanming(str2,str3))/i
x3=float(hanming(str3,str4))/i
x4=float(hanming(str1,str4))/i
x5=float(hanming(str1,str3))/i
x6=float(hanming(str2,str4))/i
aa=(x1+x2+x3+x4+x5+x6)/6
ans+=[(i,aa)]
ans.sort(lambda x,y:cmp(x[1],y[1]))
#print "hello\n"
for i in range(len(ans)):
print ans[i][0],ans[i][1]
#print len(wenben)
#print len(wenben)%29
wenben=wenben.encode('hex')
block=[re.findall(r'(.{2})',z) for z in re.findall(r'(.{58})',wenben)]#29
keyy = []
for i in range(0,29):
tmp=[]
for j in range(0,len(block)):
tmp+=[block[j][i]]
keyy+=[thechar(tmp)]
keyy="".join(keyy)
print "hello\n"
print keyy
print "hello\n"
keyy=keyy*10000
wenben=wenben.decode('hex')
an=[]
for i in range(0,len(wenben)):
an+=[chr(ord(wenben[i])^ord(keyy[i]))]
an="".join(an)
print an
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 11:34
"""
#暴力破解
import re
from Crypto.Hash import SHA
import hashlib
import itertools
import datetime
starttime = datetime.datetime.now()
hash1="67ae1a64661ac8b4494666f58c4822408dd0a3e4"
str1="QqWw%58(=0Ii*+nN"
str2=[['Q', 'q'],[ 'W', 'w'],[ '%', '5'], ['8', '('],[ '=', '0'], ['I', 'i'], ['*', '+'], ['n', 'N']]
def sha_encrypt(str):
sha = hashlib.sha1(str)
encrypts = sha.hexdigest()
return encrypts
st3="0"*8
str4=""
str3=list(st3)
for a in range(0,2):
str3[0]=str2[0][a]
for b in range(0,2):
str3[1]=str2[1][b]
for c in range(0,2):
str3[2]=str2[2][c]
for d in range(0,2):
str3[3] = str2[3][d]
for e in range(0,2):
str3[4] = str2[4][e]
for f in range(0,2):
str3[5] = str2[5][f]
for g in range(0,2):
str3[6] = str2[6][g]
for h in range(0,2):
str3[7] = str2[7][h]
newS="".join(str3)
for i in itertools.permutations(newS, 8):
str4 = sha_encrypt("".join(i))
if str4==hash1:
print "".join(i)
endtime = datetime.datetime.now()
print (endtime - starttime).seconds
exit(0)