密码学习题1

文章目录

    • 维吉尼亚密码
      • 维吉尼亚密码基本加解密
      • 维吉尼亚密码例题爆破
    • Many-Time-Pad 攻击(Cryptography-Stanford实验)
    • convert hex to base64
    • fixed XOR
    • single-byte XOR cipher
    • Detect single-character XOR
    • break repeating-key XOR
    • Break repeating-key XOR
    • MTC3 Cracking SHA1-hashed passwords

维吉尼亚密码

密码学习题1_第1张图片

维吉尼亚密码基本加解密

def VigenereEncrypto(inputt, key):
    ptlen = len(inputt)
    keylen = len(key)

    quotient = ptlen // keylen  # 商
    remainder = ptlen % keylen  # 余
    out=''
    for i in range(0,quotient):#几轮,每轮的长度为keylen
        for j in range(0,keylen):#每一轮
            c=int((ord(inputt[i*keylen+j])-ord('a')+ord(key[j]) - ord('a'))%26+ord('a'))
            out+=chr(c)

    for i in range(0,remainder):
         c=int((ord(inputt[i+keylen*quotient])-ord('a')+ord(key[j]) - ord('a'))%26+ord('a'))
         out+=chr(c)

    return out
def VigenereDecrypto (output , key) :
    ptlen = len(output)
    keylen = len(key)

    quotient = ptlen // keylen  # 商
    remainder = ptlen % keylen  # 余
    inp=''
    for i in range(0, quotient):  # 几轮,每轮的长度为keylen
        for j in range(0, keylen):  # 每一轮
            c = int((ord(input[i * keylen + j]) - ord('a') - (ord(key[j]) - ord('a'))) % 26 + ord('a'))
            inp += chr(c)
    for i in range(0, remainder):
        c = int((ord(input[i + keylen * quotient]) - ord('a') - (ord(key[j]) - ord('a'))) % 26 + ord('a'))
        inp += chr(c)
    return inp

维吉尼亚密码例题爆破

##尝试用词频分析写了一下午,还没做出来 捂脸
from string import ascii_letters, digits

# find_index_key: 确定key中index部分ascii码
# sub_arr: 当key_len和index确定时,使用key中同一位加密的子串
# 返回该子串可能使用的所有可见字符
def find_index_key(sub_arr):  # sub_arr是同一个ki的分组
    # all_ch = printable
    all_key = ascii_letters + digits + ',' + '.' + ' '
    test_key = []
    possible_key = []
    # 遍历整个ascii码(0-127)
    for x in range(0x00, 0xFF):
        test_key.append(x)
        possible_key.append(x)
    # 如果子串中所有位置都可以被ch异或为可见字符,则该ch可能为key的一部分
    for i in test_key:
        for j in sub_arr:
            if chr(i ^ j) not in all_key:
                possible_key.remove(i)
                break
    return possible_key

s = "F96DE8C227A259C87EE1DA2AED57C93FE5DA36ED4EC87EF2C63AAE5B9A7EFFD673BE4ACF7BE8923CAB1ECE7AF2DA3DA44FCF7AE29235A24C963FF0DF3CA3599A70E5DA36BF1ECE77F8DC34BE129A6CF4D126BF5B9A7CFEDF3EB850D37CF0C63AA2509A76FF9227A55B9A6FE3D720A850D97AB1DD35ED5FCE6BF0D138A84CC931B1F121B44ECE70F6C032BD56C33FF9D320ED5CDF7AFF9226BE5BDE3FF7DD21ED56CF71F5C036A94D963FF8D473A351CE3FE5DA3CB84DDB71F5C17FED51DC3FE8D732BF4D963FF3C727ED4AC87EF5DB27A451D47EFD9230BF47CA6BFEC12ABE4ADF72E29224A84CDF3FF5D720A459D47AF59232A35A9A7AE7D33FB85FCE7AF5923AA31EDB3FF7D33ABF52C33FF0D673A551D93FFCD33DA35BC831B1F43CBF1EDF67F0DF23A15B963FE5DA36ED68D378F4DC36BF5B9A7AFFD121B44ECE76FEDC73BE5DD27AFCD773BA5FC93FE5DA3CB859D26BB1C63CED5CDF3FE2D730B84CDF3FF7DD21ED5ADF7CF0D636BE1EDB79E5D721ED57CE3FE6D320ED57D469F4DC27A85A963FF3C727ED49DF3FFFDD24ED55D470E69E73AC50DE3FE5DA3ABE1EDF67F4C030A44DDF3FF5D73EA250C96BE3D327A84D963FE5DA32B91ED36BB1D132A31ED87AB1D021A255DF71B1C436BF479A7AF0C13AA14794"
ct = bytes.fromhex(s)#有很多不可打印的

# 遍历keylen和index的所有情况
for key_len in range(1, 30):
    for index in range(key_len):
        sub_arr = ct[index::key_len]  # 分组
        possible_ch = find_index_key(sub_arr)
        print('key_len = ', key_len, 'index = ', index, 'possible_ch = ', possible_ch)
        # 遍历所有可能的字符,解密ct中第一个长度为key_len的部分
        if possible_ch:
            k = []
            for j in possible_ch:
                k.append(chr(j ^ sub_arr[0]))
            print(k)

    # decryption
key = [186, 31, 145, 178, 83, 205, 62]
pt = ""
for i in range(len(ct)):
    pt += chr(ct[i] ^ key[i % 7])
print(pt)

Many-Time-Pad 攻击(Cryptography-Stanford实验)

思路:

  • 利用空格,空格异或k异或空格得到密钥,所以要得到空格异或k,即空格加密后的密文;
  • 一个大写字母与空格异或,结果为其对应的小写字母;一个小写字母与空格异或,结果为其对应的大写字母;对给出的密文两两异或后得到的数据串,判断其中[A-Z]或者[a-z]或者[0]的位置,这些位置都有可能是明文中空格的位置

假设空格来自ciphertext_a,其他密文对应ciphertext_b:

for ciphertext_a in ciphertexts:
     space_suspect_counts = [0] * len(ciphertext_a)
     for ciphertext_b in ciphertexts:
         #如果遇到自己,跳过,不和自己做异或
         if ciphertext_a == ciphertext_b:
             continue

两两异或(这样可以进行多次统计,体现在 对空格可能在的位置进行计数,max=10,若大于8,就确定他是空格),得到空格可能的位置。
如何得到key: (这里其实是假设了key都是可见字符)空格再与ciphertext_a对应位置异或,得到初步确定的key
初步确定的key再与其他密文异或,如果满足全部是在字母范围内,再添加进key值
这样其实得到11组key

import binascii

ciphertexts = [
     "315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e",
     "234c02ecbbfbafa3ed18510abd11fa724fcda2018a1a8342cf064bbde548b12b07df44ba7191d9606ef4081ffde5ad46a5069d9f7f543bedb9c861bf29c7e205132eda9382b0bc2c5c4b45f919cf3a9f1cb74151f6d551f4480c82b2cb24cc5b028aa76eb7b4ab24171ab3cdadb8356f",
     "32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de81230b59b7afb5f41afa8d661cb",
     "32510ba9aab2a8a4fd06414fb517b5605cc0aa0dc91a8908c2064ba8ad5ea06a029056f47a8ad3306ef5021eafe1ac01a81197847a5c68a1b78769a37bc8f4575432c198ccb4ef63590256e305cd3a9544ee4160ead45aef520489e7da7d835402bca670bda8eb775200b8dabbba246b130f040d8ec6447e2c767f3d30ed81ea2e4c1404e1315a1010e7229be6636aaa",
     "3f561ba9adb4b6ebec54424ba317b564418fac0dd35f8c08d31a1fe9e24fe56808c213f17c81d9607cee021dafe1e001b21ade877a5e68bea88d61b93ac5ee0d562e8e9582f5ef375f0a4ae20ed86e935de81230b59b73fb4302cd95d770c65b40aaa065f2a5e33a5a0bb5dcaba43722130f042f8ec85b7c2070",
     "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d84aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d79eccf52ff111284b4cc61d11902aebc66f2b2e436434eacc0aba938220b084800c2ca4e693522643573b2c4ce35050b0cf774201f0fe52ac9f26d71b6cf61a711cc229f77ace7aa88a2f19983122b11be87a59c355d25f8e4",
     "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce",
     "315c4eeaa8b5f8bffd11155ea506b56041c6a00c8a08854dd21a4bbde54ce56801d943ba708b8a3574f40c00fff9e00fa1439fd0654327a3bfc860b92f89ee04132ecb9298f5fd2d5e4b45e40ecc3b9d59e9417df7c95bba410e9aa2ca24c5474da2f276baa3ac325918b2daada43d6712150441c2e04f6565517f317da9d3",
     "271946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027",
     "466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83",
     "32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904",
 ]
#转换为16进制数字
ciphertexts = [binascii.unhexlify(x) for x in ciphertexts]
#print(ciphertexts)
target_ciphertext = ciphertexts[-1]
suspect_num=[]

#进行异或,zip函数将长的字符串截取到和短的字符串相同的长度
#res直接和最短的同,不会循环加密
def strxor(a, b):
     return "".join([chr(x ^ y) for x, y in zip(a, b)])
def repeat_key_xor(m,key):
    output_bytes=b''
    index=0
    for byte in m:#直接就是对应的ASCII
        #print(byte)
        #print(key[index])
        output_bytes+=bytes([byte^key[index]])
        #bytes[116,112]转为b'tp'
        if(index+1)==len(key):
            index=0
        else:
            index+=1
    return output_bytes
key = [0] * 1000
max_space_count=[0]*1000
#开始做异或,有c1⊕c2=m1⊕k⊕m2⊕k=m1⊕m2
for ciphertext_a in ciphertexts:
     space_suspect_counts = [0] * len(ciphertext_a)
     for ciphertext_b in ciphertexts:
         #如果遇到自己,跳过,不和自己做异或
         if ciphertext_a == ciphertext_b:
             continue
        #开始两两异或
         a_xor_b = strxor(ciphertext_a, ciphertext_b)
         for char_idx, xor_resulting_char in enumerate(a_xor_b):
             #一个大写字母与空格异或,结果为其对应的小写字母;一个小写字母与空格异或,结果为其对应的大写字母。
             ascii_null = "\x00"
             #isaplha()函数:判断字符串中是否是字母
             if xor_resulting_char.isalpha() or xor_resulting_char == ascii_null:
                 #获得可能的空格位置,统计这个位置和其他字符串异或出现字母的次数
                 space_suspect_counts[char_idx] += 1

    #开始假设空格位置来自于ciphertext_a,如果统计的某个位置上满足要求的次数大于等于我所期望的次数,
    #那么我们假设这个位置上就是空格且来自与ciphertext_a中对应的位置
     #space_tolerance_threshold = 0.8
     for char_idx, suspect_count in enumerate(space_suspect_counts):
         #判断出现的次数是否满足要求
         if suspect_count >= max_space_count[char_idx]:
             #通过判断得知密文这个位置上大概率是space,所以,此时 m=space,所以 c⊕space=m⊕k⊕space=k,从而可以求的key值
            whitespace = ord(" ")
            suspect_key=ciphertext_a[char_idx] ^ whitespace
             #增加判断,将 key再与其他密文对应位置异或,如果满足全部是在字母范围内,再添加进key值。
             #等于说又判断了一次???
            for ciphertext_b in ciphertexts:
                if char_idx<len(ciphertext_b):
                    if(0x41<=ciphertext_b[char_idx]^suspect_key<=0x7A):
                        max_space_count[char_idx] = suspect_count
                        key[char_idx]=suspect_key
#print("".join(chr(i)for i in key))
print(len(key))
print(len(ciphertexts[0]))
i=0
target_plaintext=[0]*11
for ciphertext_c in ciphertexts:
    # print(len(key)==len(ciphertext_c)) false
    target_plaintext[i]= strxor(ciphertext_c,key)
    #print("".join(chr(i)for i in key))
    print(f"明文{i}:{target_plaintext[i]}")
    print(len(target_plaintext[i])==len(ciphertexts[i]))
    i+=1
m10=b'The secret message is: When using a stream cipher, never use the key more than once'
key=repeat_key_xor(m10,ciphertexts[10])
#print(len(key)==len(m10))
print(key)
print(bytes([b1^b2 for b1,b2 in zip(m10,ciphertexts[10])]).hex())##key的十六进制表示
print(repeat_key_xor(ciphertexts[7],key))#第八组明文
# key1=strxor(ciphertexts[10],m10)
# print(f"key为:{key1}")
# print(bytes(key1),encoding='utf8')
# print(len(bytes(key1)))
# print(strxor(bytes(key1),ciphertexts[7]))
# print(len(strxor(bytes(key1),ciphertexts[7])))

convert hex to base64

import codecs

hex = "49276d206b696c6c696e6720796f757220627261
696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
b64 = codecs.encode(codecs.decode(hex, 'hex'), 'base64').decode()
print(b64)

fixed XOR

x1='1c0111001f010100061a024b53535009181c'
x2='686974207468652062756c6c277320657965'
x1 = bytes.fromhex(x1)
#print(x1)b'\x1c\x01\x11\x00\x1f\x01\x01\x00\x06\x1a\x02KSSP\t\x18\x1c'
x2 = bytes.fromhex(x2)
#print(x2)b"hit the bull's eye"
res=bytes([b1^b2 for b1,b2 in zip(x1,x2)])
#print(res)b"the kid don't play"
print(res.hex())

single-byte XOR cipher

def get_english_score(input_bytes):
    """Compares each input byte to a character frequency 
    chart and returns the score of a message based on the
    relative frequency the characters occur in the English
    language
    """

    # From https://en.wikipedia.org/wiki/Letter_frequency
    # with the exception of ' ', which I estimated.
    character_frequencies = {
        'a': .08167, 'b': .01492, 'c': .02782, 'd': .04253,
        'e': .12702, 'f': .02228, 'g': .02015, 'h': .06094,
        'i': .06094, 'j': .00153, 'k': .00772, 'l': .04025,
        'm': .02406, 'n': .06749, 'o': .07507, 'p': .01929,
        'q': .00095, 'r': .05987, 's': .06327, 't': .09056,
        'u': .02758, 'v': .00978, 'w': .02360, 'x': .00150,
        'y': .01974, 'z': .00074, ' ': .13000
    }
    return sum([character_frequencies.get(chr(byte), 0) for byte in input_bytes.lower()])


def single_char_xor(input_bytes, char_value):
    """Returns the result of each byte being XOR'd with a single value.
    """
    output_bytes = b''
    for byte in input_bytes:
        output_bytes += bytes([byte ^ char_value])
    return output_bytes

hexstring = '1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736'
ciphertext = bytes.fromhex(hexstring)
potential_messages = []
for key_value in range(256):
    message = single_char_xor(ciphertext, key_value)
    score = get_english_score(message)
    data = {
            'message': message,
            'score': score,
            'key': key_value
            }
    potential_messages.append(data)
best_score = sorted(potential_messages, key=lambda x: x['score'], reverse=True)[0]
for item in best_score:
    print("{}: {}".format(item.title(), best_score[item]))

Detect single-character XOR

def get_english_score(input_bytes):
    """Compares each input byte to a character frequency 
    chart and returns the score of a message based on the
    relative frequency the characters occur in the English
    language.
    """

    # From https://en.wikipedia.org/wiki/Letter_frequency
    # with the exception of ' ', which I estimated.
    character_frequencies = {
        'a': .08167, 'b': .01492, 'c': .02782, 'd': .04253,
        'e': .12702, 'f': .02228, 'g': .02015, 'h': .06094,
        'i': .06094, 'j': .00153, 'k': .00772, 'l': .04025,
        'm': .02406, 'n': .06749, 'o': .07507, 'p': .01929,
        'q': .00095, 'r': .05987, 's': .06327, 't': .09056,
        'u': .02758, 'v': .00978, 'w': .02360, 'x': .00150,
        'y': .01974, 'z': .00074, ' ': .13000
    }
    return sum([character_frequencies.get(chr(byte), 0) for byte in input_bytes.lower()])


def single_char_xor(input_bytes, char_value):
    """Returns the result of each byte being XOR'd with a single value.
    """
    output_bytes = b''
    for byte in input_bytes:
        output_bytes += bytes([byte ^ char_value])
    return output_bytes


def bruteforce_single_char_xor(ciphertext):
    """Performs a singlechar xor for each possible value(0,255), and
    assigns a score based on character frequency. Returns the result
    with the highest score.
    """
    potential_messages = []
    for key_value in range(256):
        message = single_char_xor(ciphertext, key_value)
        score = get_english_score(message)
        data = {
            'message': message,
            'score': score,
            'key': key_value
        }
        potential_messages.append(data)
    return sorted(potential_messages, key=lambda x: x['score'], reverse=True)[0]


def main():
    ciphers = open('ex1.4.txt').read().splitlines()#每行放在一个列表中
    potential_plaintext = []
    for hexstring in ciphers:
        ciphertext = bytes.fromhex(hexstring)
        potential_plaintext.append(bruteforce_single_char_xor(ciphertext))
    print(potential_plaintext)
    best_score = sorted(potential_plaintext, key=lambda x: x['score'], reverse=True)[0]
    for item in best_score:
        print("{}: {}".format(item.title(), best_score[item]))


if __name__ == '__main__':
    main()

break repeating-key XOR

def repeating_key_xor(key, string):
    # i is the position within the key
    i = 0
    arr = []
    for ch in string:
        arr.append(ord(ch) ^ ord(key[i]))
        i += 1
        if (i == len(key)):
            i = 0
    ##ascii转十六进制
    #bytearray 这里将数字列表转为 字节串
    return hexlify(bytearray(arr))
def repeat_key_xor(m,key):
    output_bytes=b''
    index=0
    for byte in m:
        output_bytes+=bytes([byte^key[index]])
        #bytes[116,112]转为b'tp'
        if(index+1)==len(key):
            index=0
        else:
            index+=1
    return output_bytes

m=b"Burning 'em, if you ain't quick and nimble"
m1=b'I go crazy when I hear a cymbal'
key=b'ICE'
c=repeat_key_xor(m,key)
c1=repeat_key_xor(m1,key)
print(c.hex())
print(c1.hex())
#msg=[3, 159, 11, 19, 148, 72, 65, 168, 50, 178, 66, 27, 158, 175, 109, 152, 54, 129, 62, 201, 217, 68, 165, 200, 52, 122, 124, 166, 154, 163, 77, 141, 192, 223, 112, 227, 67, 196, 0, 10, 42, 227, 88, 116, 206, 117, 230, 76, 49, 0]
print(bytearray(msg))#转为字节b'\x03\x9f\x0b\x13\x94HA\xa82\xb2B\x1b\x9e\xafm\x986\x81>\xc9\xd9D\xa5\xc84z|\xa6\x9a\xa3M\x8d\xc0\xdfp\xe3C\xc4\x00\n*\xe3Xt\xceu\xe6L1\x00'

Break repeating-key XOR

import base64

def hamm (s1, s2):
    tot = 0
    for a,b in zip(s1,s2):
        tot += (bin(a^b).count('1'))
    #print('test Hamming distance is: ', tot)
    return(tot)
#print(hamm(b'this is a test',b'wokka wokka!!!'))
def find_key_len(c):
    aver_hamm=[]
    for keylen in range(2,41):
        #将密文分组
        tmp_aver_hamm=[]
        test1 = c
        while len(test1) >= (2 * keylen):
            x = test1[:keylen]
            y = test1[keylen:(2 * keylen)]
            # take the hamming distance and normalize by keysize
            score = hamm(x, y) / keylen
            test1 = test1[ keylen:]
            tmp_aver_hamm.append(score)
        res={
                'keylength': keylen,
                'avg distance': sum(tmp_aver_hamm)/len(tmp_aver_hamm)
            }
        aver_hamm.append(res)

    possible_key_length = sorted(aver_hamm, key=lambda x: x['avg distance'])[0]
    return  possible_key_length['keylength']
##按照同一密钥进行分组c[::keylen]
##每个就转化成了 single_key_XOR: 根据字母出现的频率得到分数最高的
def get_english_score(input_bytes):

    character_frequencies = {
        'a': .08167, 'b': .01492, 'c': .02782, 'd': .04253,
        'e': .12702, 'f': .02228, 'g': .02015, 'h': .06094,
        'i': .06094, 'j': .00153, 'k': .00772, 'l': .04025,
        'm': .02406, 'n': .06749, 'o': .07507, 'p': .01929,
        'q': .00095, 'r': .05987, 's': .06327, 't': .09056,
        'u': .02758, 'v': .00978, 'w': .02360, 'x': .00150,
        'y': .01974, 'z': .00074, ' ': .13000
    }
    return sum([character_frequencies.get(chr(byte), 0) for byte in input_bytes.lower()])
def repeat_key_xor(m,key):
    output_bytes=b''
    index=0
    for byte in m:#直接就是对应的ASCII
        #print(byte)
        #print(key[index])
        output_bytes+=bytes([byte^key[index]])
        #bytes[116,112]转为b'tp'
        if(index+1)==len(key):
            index=0
        else:
            index+=1
    return output_bytes

def single_char_xor(input_bytes, char_value):
    """Returns the result of each byte being XOR'd with a single value.
    """
    output_bytes = b''
    for byte in input_bytes:
        output_bytes += bytes([byte ^ char_value])
    return output_bytes
def bruteforce_single_char_xor(ciphertext):
    """Performs a singlechar xor for each possible value(0,255), and
    assigns a score based on character frequency. Returns the result
    with the highest score.
    """
    potential_messages = []
    for key_value in range(256):
        message = single_char_xor(ciphertext, key_value)
        score = get_english_score(message)
        data = {
            'message': message,
            'score': score,
            'key': key_value
        }
        potential_messages.append(data)
    return sorted(potential_messages, key=lambda x: x['score'], reverse=True)[0]['key']#最大的

cipher=open('ex1.4.txt').read().replace('\n','')
# convert to bytes
cipher=base64.b64decode(cipher)
keylen=find_key_len(cipher)
print(keylen)
#分组
key=[]
for index in range(keylen):
    sub_cipher=cipher[index::keylen]
    ## single_key_XOR:
    key.append(bruteforce_single_char_xor(sub_cipher))
print(''.join(chr(i) for i in key))
print(repeat_key_xor(cipher,bytes(''.join(chr(i) for i in key),encoding='utf8')))

MTC3 Cracking SHA1-hashed passwords

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']]
##str2是用来交换的,比如 Qxxx xxxx xxxx都不对,就换成q xxxxxxxxx 时间复杂度为0()由于需要在10s之内求解,
str4=""
str3=[0]*8
#首先要知道密码有多少位吧。。咋确定就是8位呢
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 =hashlib.sha1("".join(i).encode("utf-8")).hexdigest()
                                   if str4==hash1:
                                       print("".join(i))
                                       endtime = datetime.datetime.now()
                                       print(f"运行时间是:{(endtime - starttime).seconds}s")

你可能感兴趣的:(密码学,python,安全)