西电现代密码学实验一

week1

python 复制代码
import binascii

ciphertexts = [
     "315c4eeaa8b5f8aaf9174145bf43e1784b8fa00dc71d885a804e5ee9fa40b16349c146fb778cdf2d3aff021dfff5b403b510d0d0455468aeb98622b137dae857553ccd8883a7bc37520e06e515d22c954eba5025b8cc57ee59418ce7dc6bc41556bdb36bbca3e8774301fbcaa3b83b220809560987815f65286764703de0f3d524400a19b159610b11ef3e",
     "234c02ecbbfbafa3ed18510abd11fa724fcda2018a1a8342cf064bbde548b12b07df44ba7191d9606ef4081ffde5ad46a5069d9f7f543bedb9c861bf29c7e205132eda9382b0bc2c5c4b45f919cf3a9f1cb74151f6d551f4480c82b2cb24cc5b028aa76eb7b4ab24171ab3cdadb8356f",
     "32510ba9a7b2bba9b8005d43a304b5714cc0bb0c8a34884dd91304b8ad40b62b07df44ba6e9d8a2368e51d04e0e7b207b70b9b8261112bacb6c866a232dfe257527dc29398f5f3251a0d47e503c66e935de81230b59b7afb5f41afa8d661cb",
     "32510ba9aab2a8a4fd06414fb517b5605cc0aa0dc91a8908c2064ba8ad5ea06a029056f47a8ad3306ef5021eafe1ac01a81197847a5c68a1b78769a37bc8f4575432c198ccb4ef63590256e305cd3a9544ee4160ead45aef520489e7da7d835402bca670bda8eb775200b8dabbba246b130f040d8ec6447e2c767f3d30ed81ea2e4c1404e1315a1010e7229be6636aaa",
     "3f561ba9adb4b6ebec54424ba317b564418fac0dd35f8c08d31a1fe9e24fe56808c213f17c81d9607cee021dafe1e001b21ade877a5e68bea88d61b93ac5ee0d562e8e9582f5ef375f0a4ae20ed86e935de81230b59b73fb4302cd95d770c65b40aaa065f2a5e33a5a0bb5dcaba43722130f042f8ec85b7c2070",
     "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d84aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d79eccf52ff111284b4cc61d11902aebc66f2b2e436434eacc0aba938220b084800c2ca4e693522643573b2c4ce35050b0cf774201f0fe52ac9f26d71b6cf61a711cc229f77ace7aa88a2f19983122b11be87a59c355d25f8e4",
     "32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce",
     "315c4eeaa8b5f8bffd11155ea506b56041c6a00c8a08854dd21a4bbde54ce56801d943ba708b8a3574f40c00fff9e00fa1439fd0654327a3bfc860b92f89ee04132ecb9298f5fd2d5e4b45e40ecc3b9d59e9417df7c95bba410e9aa2ca24c5474da2f276baa3ac325918b2daada43d6712150441c2e04f6565517f317da9d3",
     "271946f9bbb2aeadec111841a81abc300ecaa01bd8069d5cc91005e9fe4aad6e04d513e96d99de2569bc5e50eeeca709b50a8a987f4264edb6896fb537d0a716132ddc938fb0f836480e06ed0fcd6e9759f40462f9cf57f4564186a2c1778f1543efa270bda5e933421cbe88a4a52222190f471e9bd15f652b653b7071aec59a2705081ffe72651d08f822c9ed6d76e48b63ab15d0208573a7eef027",
     "466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83",
     "32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904",
 ]

target = "32510ba9babebbbefd001547a810e67149caee11d945cd7fc81a05e9f85aac650e9052ba6a8cd8257bf14d13e6f0a803b54fde9e77472dbff89d71b57bddef121336cb85ccb8f3315f4b52e301d16e9f52f904"
length = len(ciphertexts)

# 16进制数字转换为asscii码对应字符
ciphertexts = [binascii.unhexlify(x) for x in ciphertexts]

# 这个方法可以直接对十六进制串进行异或操作
def strxor(a, b):     # xor two strings of different lengths
    return "".join([chr(x ^ y) for x, y in zip(a, b)])

# 对字符串里每个字符依次做异或操作,因此使用之前必须把要进行操作的字符串划分成一个一个的形式
# 这里本来相用第一种方法,但是获取的key好像无法完成转换成数字形式就放弃了
def stror1(a, b):
    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 find_letter(s):
    #返回给定字符串中给定字母的位置
    position = []
    for index in range(len(s)):
        #考虑到空格异或为0的情况可能较多
        if (s[index] >= 'A' and s[index] <= 'Z') or (s[index] >= 'a' and s[index] <= 'z') or s[index] == chr(0):
            # space_counts[index] += 1
            position.append(index)
    return position

# 计算空格位置的可能性
def space_possibility(s):
    space_new = []
    for position in range(400):
        count = 0
        for idx_i in range(length - 1):
            if position in s[idx_i]:
                count += 1
        if count > 7:  # 如果异或后字母出现次数大于7次,认为明文中此处为空格
            space_new.append(position)
    return space_new

# 找到可能是空格符的位置
def find_space(ciphertexts):
    space_possib = []  # 用于保存可能是空格符的位置
    # 使用双重循环实现字符串两两异或
    for ciphertext_i in ciphertexts:
        space = []  # 用于保存可能是空格符的位置
        for ciphertext_j in ciphertexts:
            # 不和自己做异或
            if ciphertext_i == ciphertext_j:
                continue
            xor_res = strxor(ciphertext_i, ciphertext_j)
            # 记录每一条明文中可能空格符的位置
            space.append(find_letter(xor_res))
        # 对空格位置做可能性判断
        space_possib.append(space_possibility(space))
    return space_possib

#计算获得对应密钥Key
def cal_key(cipher):
    space_possib = find_space(cipher)
    key = [0] * 200  #存放key
    for cipher_idx in range(length):
        for position in range(len(space_possib[cipher_idx])):
            idx = space_possib[cipher_idx][position] #十六进制,用2位表示
            a = cipher[cipher_idx][idx]
            key[space_possib[cipher_idx][position]] = a ^ ord(" ") # 计算密钥,获得结果十进制(ascii码)

    key_str = "" #空串用于存放密钥
    for k in key:
        key_str += chr(k)#转化为
    return key_str  #获得密钥串

if __name__ == '__main__':
    # space_possib = find_space(ciphertexts)
    key = cal_key(ciphertexts)
    result = ""
    f = ''.join([chr(int(d, 16)) for d in [target[i:i + 2] for i in range(0, len(target), 2)]])
    for letter in stror1(f, key):
            result += letter
    print(result)
PA1
python 复制代码
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:00
"""

# 类维吉尼亚密码破解(使用字节级XOR运算)
def findindexkey(subarr):
    """找出将密文subarr解密成可见字符的所有可能密钥值"""
    # 可见字符范围:ASCII 32-125(空格到~)
    visiable_chars = [chr(x) for x in range(32, 126)]
    
    ans_keys = list(range(0x00, 0xFF))  # 所有可能的密钥值(0-255)
    
    for key in list(ans_keys):  # 遍历所有可能的密钥
        for s in subarr:
            # 解密后字符不在可见范围内,则排除该密钥
            if chr(s ^ key) not in visiable_chars:
                ans_keys.remove(key)
                break
    return ans_keys


# 密文(十六进制字符串)
strmi = 'F96DE8C227A259C87EE1DA2AED57C93FE5DA36ED4EC87EF2C63AAE5B9A7EFFD673BE4ACF7BE8923C\
AB1ECE7AF2DA3DA44FCF7AE29235A24C963FF0DF3CA3599A70E5DA36BF1ECE77F8DC34BE129A6CF4D126BF\
5B9A7CFEDF3EB850D37CF0C63AA2509A76FF9227A55B9A6FE3D720A850D97AB1DD35ED5FCE6BF0D138A84C\
C931B1F121B44ECE70F6C032BD56C33FF9D320ED5CDF7AFF9226BE5BDE3FF7DD21ED56CF71F5C036A94D96\
3FF8D473A351CE3FE5DA3CB84DDB71F5C17FED51DC3FE8D732BF4D963FF3C727ED4AC87EF5DB27A451D47E\
FD9230BF47CA6BFEC12ABE4ADF72E29224A84CDF3FF5D720A459D47AF59232A35A9A7AE7D33FB85FCE7AF5\
923AA31EDB3FF7D33ABF52C33FF0D673A551D93FFCD33DA35BC831B1F43CBF1EDF67F0DF23A15B963FE5DA\
36ED68D378F4DC36BF5B9A7AFFD121B44ECE76FEDC73BE5DD27AFCD773BA5FC93FE5DA3CB859D26BB1C63C\
ED5CDF3FE2D730B84CDF3FF7DD21ED5ADF7CF0D636BE1EDB79E5D721ED57CE3FE6D320ED57D469F4DC27A8\
5A963FF3C727ED49DF3FFFDD24ED55D470E69E73AC50DE3FE5DA3ABE1EDF67F4C030A44DDF3FF5D73EA250\
C96BE3D327A84D963FE5DA32B91ED36BB1D132A31ED87AB1D021A255DF71B1C436BF479A7AF0C13AA14794'

# 将十六进制密文转换为字节数组(每个元素为十进制值)
arr = []
for x in range(0, len(strmi), 2):
    arr.append(int(strmi[x:x+2], 16))

# 枚举可能的密钥长度(1-14)
for keylen in range(1, 14):
    for index in range(keylen):  # 对密钥的每个位置进行测试
        # 提取由同一密钥字节加密的密文片段(每隔keylen取一个)
        subarr = arr[index::keylen]
        ans_keys = findindexkey(subarr)
        print(f'keylen={keylen}, index={index}, keys={ans_keys}')
        
        if ans_keys:  # 若存在可能的密钥,尝试解密第一个字符
            ch = [chr(key ^ subarr[0]) for key in ans_keys]
            print(ch)

print('###############')
import string

def findindexkey2(subarr):
    """更严格的密钥筛选:仅允许英文、数字、逗号、句号和空格"""
    test_chars = string.ascii_letters + string.digits + ',.' + ' '
    ans_keys = list(range(0x00, 0xFF))  # 所有可能的密钥值(0-255)
    
    for key in list(ans_keys):
        for s in subarr:
            if chr(s ^ key) not in test_chars:
                ans_keys.remove(key)
                break
    return ans_keys

# 确定密钥长度为7后,提取完整密钥
vigenerekeys = []
for index in range(7):
    subarr = arr[index::7]  # 按密钥长度7分组
    vigenerekeys.append(findindexkey2(subarr))

print(vigenerekeys)  # 输出密钥:[[186], [31], [145], [178], [83], [205], [62]]

print("#########")
# 解密密文
ming = ''
for i in range(len(arr)):
    # 循环使用密钥的每个字节
    key = vigenerekeys[i % 7][0]
    ming += chr(arr[i] ^ key)

print(ming)

set1

1

python 复制代码
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:01
"""

import base64
import binascii

def hex_to_base64(hex_string):
    # 先将十六进制字符串转换为字节流,再进行Base64编码
    hex_bytes = binascii.unhexlify(hex_string)
    # 编码后转换为字符串返回
    return base64.b64encode(hex_bytes).decode('utf-8')

string = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"
print(hex_to_base64(string))

2

python 复制代码
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 9:08
"""

import binascii

def xor_strings(xs, ys):
    """对两个字节流进行XOR运算,返回结果字节流"""
    return bytes(x ^ y for x, y in zip(xs, ys))

if __name__ == '__main__':
    string1 = '1c0111001f010100061a024b53535009181c'
    string2 = '686974207468652062756c6c277320657965'
    
    # 将十六进制字符串转换为字节流(Python 3推荐方式)
    hex_bytes1 = binascii.unhexlify(string1)
    hex_bytes2 = binascii.unhexlify(string2)
    
    # 执行XOR运算并转换为十六进制字符串
    result_bytes = xor_strings(hex_bytes1, hex_bytes2)
    result = binascii.hexlify(result_bytes).decode('utf-8')
    
    print(result)

3

python 复制代码
#coding=utf-8
import re

# 避免使用关键字作为变量名,改为hex_str
hex_str = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
max_score = 0  # 记录最大匹配分数
best_ans = ""  # 记录最佳解密结果
best_key = ""  # 记录最佳密钥

for i in range(0, 129):
    tmp = []
    # 遍历十六进制字符串中的每两个字符(一个字节)
    for j in re.findall(".{2}", hex_str):
        # 解密:当前密钥与十六进制值异或,转换为字符
        tmp.append(chr(i ^ int(j, 16)))
    tmp_str = "".join(tmp)
    
    # 统计小写字母数量作为评分标准
    current_score = 0
    for char in tmp_str:
        if 'a' <= char <= 'z':
            current_score += 1
    
    # 更新最佳结果
    if current_score > max_score:
        max_score = current_score
        best_ans = tmp_str
        best_key = chr(i)

# Python 3中print为函数,使用括号
print(best_key)
print(best_ans)

4

python 复制代码
#coding=utf-8
import re

# 使用上下文管理器安全读取文件,兼容Python 3
wenben = []
with open("4.txt", "r") as f:
    for line in f.readlines():
        wenben.append(line.replace("\n", ""))  # 移除换行符并添加到列表

max_score = 0  # 记录最大匹配分数
best_ans = ""   # 最佳解密结果
best_key = ""   # 最佳密钥
best_c = ""     # 最佳密文

for k in wenben:
    for i in range(0, 129):
        tmp = []
        # 遍历每个十六进制字节
        for j in re.findall(".{2}", k):
            # 解密:当前密钥与十六进制值异或
            tmp.append(chr(i ^ int(j, 16)))
        tmp_str = "".join(tmp)
        
        # 统计字母和空格的数量作为评分标准
        current_score = len(re.findall(r'[a-zA-Z ]', tmp_str))
        
        # 更新最佳结果
        if current_score > max_score:
            max_score = current_score
            best_ans = tmp_str
            best_c = k
            best_key = chr(i)

# Python 3的print函数语法
print(best_c)
print(best_key)
print(best_ans)

5

python 复制代码
# -*- coding: utf-8 -*-

def xor_repeat_key(key, string):
    key_len = len(key)
    str_result = ''
    for index, ch in enumerate(string):
        n = index % key_len  # 循环使用密钥
        # 对每个字符进行XOR运算
        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'
    # 处理十六进制编码并修正Python 3语法
    encrypted = xor_repeat_key(key, string1)
    # 将加密结果转换为十六进制字符串(Python 3方式)
    hex_result = encrypted.encode('utf-8').hex()
    print(hex_result)


if __name__ == '__main__':
    main()

6

python 复制代码
#coding:utf-8
import re
import base64
import binascii

# 读取并解码Base64密文
with open("6.txt", "r") as fp:
    # 读取每一行并解码,拼接为字节流
    wenben = b"".join([base64.b64decode(line.strip()) for line in fp.readlines()])

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
    # 取较短长度进行比较
    min_len = min(len(x), len(y))
    for i in range(min_len):
        # 计算异或结果中1的个数
        t = x[i] ^ y[i]
        while t:
            if t & 1:
                num += 1
            t >>= 1
    return num

def thechar(st1):
    """找到最佳的单字节解密密钥"""
    max_score = 0
    best_key = ''
    for i in range(0, 256):
        tmp = []
        for j in range(len(st1)):
            # 异或操作解密
            tmp.append(chr(i ^ int(st1[j], 16)))
        tmpstr = "".join(tmp)
        # 计算英文文本评分
        score = english_test(tmpstr)
        if score > max_score:
            max_score = score
            best_key = chr(i)
    return best_key

# 分析可能的密钥长度(1到40)
ans = []
for key_len in range(1, 41):
    # 将密文分成4个块
    blocks = []
    for i in range(4):
        start = i * key_len
        end = start + key_len
        blocks.append(wenben[start:end])
    
    # 计算所有块之间的平均汉明距离
    distances = []
    for i in range(4):
        for j in range(i+1, 4):
            distances.append(hanming(blocks[i], blocks[j]) / key_len)
    
    avg_distance = sum(distances) / len(distances)
    ans.append((key_len, avg_distance))

# 按汉明距离排序(Python 3使用key参数替代cmp)
ans.sort(key=lambda x: x[1])

# 打印可能的密钥长度及其平均汉明距离
for item in ans:
    print(f"密钥长度: {item[0]}, 平均汉明距离: {item[1]}")

# 确定密钥长度为29(根据分析结果)
key_length = 29
print(f"\n选择的密钥长度: {key_length}")

# 将密文转换为十六进制字符串
hex_wenben = binascii.hexlify(wenben).decode('utf-8')

# 按密钥长度分块(每个块包含29个字节,对应58个十六进制字符)
block_size = key_length * 2  # 每个字节对应2个十六进制字符
blocks = re.findall(rf'.{{{block_size}}}', hex_wenben)
# 分割每个块为字节
blocks = [re.findall(r'(.{2})', block) for block in blocks]

# 确定密钥的每个字符
keyy = []
for i in range(key_length):
    # 收集每个块的第i个字节
    column = [block[i] for block in blocks if i < len(block)]
    # 找到最佳解密字符
    key_char = thechar(column)
    keyy.append(key_char)

keyy = "".join(keyy)
print("\n找到的密钥:")
print(keyy)

# 解密密文
an = []
key_bytes = keyy.encode('utf-8')
for i in range(len(wenben)):
    # 循环使用密钥
    decrypted_byte = wenben[i] ^ key_bytes[i % key_length]
    an.append(chr(decrypted_byte))

# 输出解密结果
print("\n解密结果:")
print("".join(an))
keyboard
python 复制代码
# _*_ coding:utf-8 _*_
"""
@author km
@time: 2019/10/18 11:34
"""
# 暴力破解SHA1哈希值
import re
import hashlib
import itertools
import datetime

starttime = datetime.datetime.now()
hash1 = "67ae1a64661ac8b4494666f58c4822408dd0a3e4"  # 目标哈希值

# 字符选择集:每个位置有2种可选字符
str2 = [
    ['Q', 'q'],   # 位置0的可选字符
    ['W', 'w'],   # 位置1的可选字符
    ['%', '5'],   # 位置2的可选字符
    ['8', '('],   # 位置3的可选字符
    ['=', '0'],   # 位置4的可选字符
    ['I', 'i'],   # 位置5的可选字符
    ['*', '+'],   # 位置6的可选字符
    ['n', 'N']    # 位置7的可选字符
]

def sha_encrypt(s):
    """计算字符串的SHA1哈希值"""
    sha = hashlib.sha1(s.encode('utf-8'))  # Python 3需要先编码为字节流
    return sha.hexdigest()

# 初始化8位字符列表
str3 = ['0'] * 8

# 8层循环:为每个位置选择字符(每个位置2种选择)
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):
                                    candidate = "".join(i)
                                    hash_result = sha_encrypt(candidate)
                                    if hash_result == hash1:
                                        print(candidate)  # 找到匹配的明文
                                        endtime = datetime.datetime.now()
                                        print((endtime - starttime).seconds)  # 输出耗时
                                        exit(0)
相关推荐
FriendshipT6 小时前
图像生成:PyTorch从零开始实现一个简单的扩散模型
人工智能·pytorch·python
五条凪6 小时前
Verilog-Eval-v1基准测试集搭建指南
开发语言·人工智能·算法·语言模型
初学小白...6 小时前
反射概述and获得反射对象
开发语言·python
后藤十八里7 小时前
2025python学习笔记Part2
开发语言·python
寒秋丶7 小时前
Milvus:向量字段-二进制向量、稀疏向量与密集向量(六)
数据库·人工智能·python·ai·ai编程·milvus·向量数据库
材料科学研究7 小时前
深度学习PINN!从入门到精通!
python·深度学习·神经网络·pinn
屹奕7 小时前
基于EasyExcel实现Excel导出功能
java·开发语言·spring boot·excel
hixiong1237 小时前
C# OpencvSharp使用lpd_yunet进行车牌检测
开发语言·opencv·计算机视觉·c#
Lj2_jOker7 小时前
QT 给Qimage数据赋值,显示异常,像素对齐的坑
开发语言·前端·qt