CTF-希尔加解密

这篇文章介绍了作者基于Python编写的希尔加密算法,通过给定字母表和私钥字符串,生成并使用不同维度和重叠的加密矩阵进行加解密操作,并展示了实际的加密和解密结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于希尔加解密很多writeup都说用在线工具,所以研究了一下,写了一个方便的加解密python代码,根据给定的字母表及私钥字符串,尝试不同纬度不同重叠的加密矩阵输出加解密结果。运行效果如下:

代码文件Hill希尔加解密_final.py

import numpy as np
import string
# 导入自定义模块以创建矩阵和转换字符串
from util_create_matrix import create_matrix_from_list, create_numbers_from_string

# 定义了使用的字符集,包括所有小写字母、空格、逗号和句点
alphabet = "abcdefghijklmnopqrstuvwxyz ,."
# 密钥短语,用于生成加密/解密所需的密钥矩阵
key_phrase = "www.verymuch.net"

def mod_inverse(a, m):
    """
    计算模m下a的逆元。逆元是满足 (a * x) % m == 1 的整数x。
    """
    a = a % m
    for x in range(1, m):
        if (a * x) % m == 1:
            return x
    return None

def matrix_mod_inv(matrix, modulus):
    """
    计算给定矩阵在模modulus下的逆矩阵。这是通过先计算矩阵的行列式及其模逆,
    然后应用数学公式来实现的。
    """
    det = int(np.round(np.linalg.det(matrix)))  # 计算行列式并取整
    det_inv = mod_inverse(det, modulus)  # 计算行列式的模逆
    matrix_modulus_inv = (
        det_inv * np.round(det * np.linalg.inv(matrix)).astype(int) % modulus
    )
    return matrix_modulus_inv

def char_to_num(char):
    """
    将字符转换为对应的数字。这里将空格、逗号和句号也视为字符集的一部分。
    """
    if char == ' ':
        return 26
    elif char == ',':
        return 27
    elif char == '.':
        return 28
    else:
        return string.ascii_lowercase.index(char)

def num_to_char(num):
    """
    将数字转换回对应的字符。与char_to_num函数相对应。
    """
    if num == 26:
        return ' '
    elif num == 27:
        return ','
    elif num == 28:
        return '.'
    else:
        return string.ascii_lowercase[num]

def prepare_text(text, block_size):
    """
    准备文本以适应加密/解密过程,确保文本长度是block_size的倍数,不足部分以'x'填充。
    """
    while len(text) % block_size != 0:
        text += 'x'
    return text

def text_to_numbers(text):
    """
    将文本字符串转换为数字序列,每个字符映射到其在字母表中的位置。
    """
    return [char_to_num(char) for char in text]

def numbers_to_text(numbers):
    """
    将数字序列转换回文本字符串,每个数字映射回其对应的字符。
    """
    return ''.join(num_to_char(number) for number in numbers)

def hill_encrypt_decrypt(text, key_matrix, operation="encrypt"):
    """
    执行希尔加密或解密操作。根据操作类型,此函数使用key_matrix直接加密,
    或首先计算其逆矩阵进行解密。
    """
    block_size = key_matrix.shape[0]  # 确定密钥矩阵的大小,用于分块大小
    text = prepare_text(text, block_size)  # 根据分块大小调整文本长度
    text_numbers = text_to_numbers(text)  # 将文本转换为数字序列
    result = []  # 存储加密或解密结果的数字序列

    # 如果是解密操作,计算密钥矩阵的逆矩阵
    if operation == "decrypt":
        key_matrix = matrix_mod_inv(key_matrix, 29) 

    # 对每个文本块执行矩阵乘法和模运算
    for i in range(0, len(text_numbers), block_size):
        block = np.array(text_numbers[i:i+block_size])
        encrypted_block = np.dot(key_matrix, block) % 29  # 模29保证结果在字母表范围内
        result.extend(encrypted_block)
    return numbers_to_text(result)  # 将数字序列转换回文本

# 主函数,负责用户交互和调用加密/解密函数
def main():
    choice = input("请选择操作:\n1. 加密\n2. 解密\n")  # 用户选择加密还是解密
    text = input("请输入明文:" if choice == '1' else "请输入密文:")  # 获取用户输入的文本
    key_numbers = create_numbers_from_string(alphabet, key_phrase, 0)  # 根据密钥短语生成密钥数字序列
    
    # 尝试不同的密钥矩阵维度和重叠度进行加密/解密
    for dim in range(2, 5):  # 维度从2到4
        for overlap in range(1, 5):  # 重叠度从1到4
            if overlap > dim:
                break  # 如果重叠度大于维度,则不再尝试
            try:
                key_matrix = np.array(create_matrix_from_list(key_numbers, dim, overlap))
                if choice == '1':
                    encrypted = hill_encrypt_decrypt(text, key_matrix, "encrypt")
                    print(f"使用dim={dim}, overlap={overlap}加密后的密文:{encrypted}")
                else:
                    decrypted = hill_encrypt_decrypt(text, key_matrix,"decrypt")
                    print(f"使用dim={dim}, overlap={overlap}解密后的明文:{decrypted}")
            except ValueError as e:
                print(e)
                break  # 如果出现异常,则停止尝试当前维度和重叠度的组合

if __name__ == "__main__":
    main()  # 运行主函数

'''
请选择操作:
1. 加密
2. 解密
1
请输入明文:love and peaceee
使用dim=2, overlap=1加密后的密文:....vveeddbbqqcc
使用dim=2, overlap=2加密后的密文:....vveeddbbqqcc
使用dim=3, overlap=1加密后的密文: cgweozrcmhmrik, q
使用dim=3, overlap=2加密后的密文: hcwwezhrmmhrmi,u 
使用dim=3, overlap=3加密后的密文:   wwwzzzmmmrrr,,,
使用dim=4, overlap=1加密后的密文:waoootu.epj,nv o
使用dim=4, overlap=2加密后的密文:wspooq,uedhjnyt 
使用dim=4, overlap=3加密后的密文:wesaonqte.dpnjyv
使用dim=4, overlap=4加密后的密文:wwwwooooeeeennnn

1. 加密
2. 解密
2
请输入密文:waoootu.epj,nv o
Singular matrix
使用dim=3, overlap=1解密后的明文:tpzhhnkhfxvqotthau
使用dim=3, overlap=2解密后的明文:ftgczahelg .ielcjq
Singular matrix
使用dim=4, overlap=1解密后的明文:love and peaceee
使用dim=4, overlap=2解密后的明文:e.nlnldaayiekhkb
使用dim=4, overlap=3解密后的明文:znwwvkzandgqvdex
Singular matrix
'''

代码文件util_create_matrix.py

def create_matrix_from_list(numbers, dim=4, overlap=1):
    """
    根据提供的数字列表、矩阵维度和重叠度,生成指定维度的矩阵。
    
    参数:
    - numbers: 数字列表,用于填充矩阵。
    - dim: 整数,表示矩阵的维度(例如2x2, 3x3, 4x4等)。
    - overlap: 整数,指定相邻行之间的重叠数字数量。
    
    返回:
    - 生成的矩阵,为dim x dim大小。如果提供的数字不足以填满矩阵,返回错误信息。
    """
    # 计算根据维度和重叠度需要的数字总数
    total_numbers_needed = dim * dim - (dim - 1) * overlap

    # 如果提供的数字不足以构成矩阵,返回错误信息
    if len(numbers) < total_numbers_needed:
        return "提供的数字不足以形成指定维度的矩阵。"

    # 构造矩阵
    matrix = []
    for i in range(dim):
        start_index = i * (dim - overlap)  # 计算当前行起始数字的索引
        end_index = start_index + dim  # 计算当前行结束数字的索引
        row = numbers[start_index:end_index]  # 提取当前行的数字
        matrix.append(row)  # 将当前行添加到矩阵中

    return matrix

# 示例:使用整数参数调用函数并打印结果
numbers_list = [22, 22, 22, 28, 21, 4, 17, 24, 12, 20, 2, 7, 28, 13, 4, 19]
dim = 4  # 矩阵的维度
overlap = 1  # 行之间的重叠数字数量
matrix = create_matrix_from_list(numbers_list, dim, overlap)
print(matrix)

def create_numbers_from_string(alphabet, key_string, start=0):
    """
    根据给定的字母表和字符串,返回一个数字列表,表示字符串中每个字符在字母表中的位置。
    位置计数从start参数指定的数字开始。

    参数:
    - alphabet: 字符串,定义可用字符的序列。
    - key_string: 字符串,需要转换为数字列表的文本。
    - start: 整数,数字列表的起始值,默认为0。

    返回:
    - 数字列表,其中包含key_string中每个字符对应的位置。
    """
    return [alphabet.index(char) + start for char in key_string]

# 示例:将字符串转换为数字列表并打印结果
alphabet = "abcdefghijklmnopqrstuvwxyz ,."
print(create_numbers_from_string(alphabet, "www.verymuch.net", 0))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铭记北宸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值