希尔密码(Hill)

简介: 希尔密码(Hill)

希尔密码(Hill)

  • 加密对象: 小写字母
  • 加密原理:
  • 该加密方式使用了矩阵的相关知识,包括矩阵的逆,矩阵相乘。
  • a~z对应于1~
  • 26, 将明文转为数字。同理,在解密是也需要转为数字
a b c d e f g h i j k l m n o p q r s t u v w x y z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

  • 密文 = 秘钥矩阵*明文矩阵 (mod 26)


明文 = 秘钥矩阵的逆矩阵*密文矩阵 (mod 26)


秘钥矩阵是一个方阵,nxn阶。该矩阵的行列式必须与26互质


明文矩阵构建是依据秘钥矩阵的阶数来的,由于加密时需要相乘,故秘钥矩阵的行数(n)要等于明文矩阵的列数,不足的补0。密文矩阵同理。注意: 矩阵的构建是将明文分为多个列矩阵(我看大多数文档都是这样的),如对应于(1, 2, 3, 4),如果构成二维的话,就应该是[[1,3],[2,4]],而不是[[1,2],[3,4]]…


得到密文的数值后在查表转为字符就是密文了。其实加密过程和解密过程是一样的,只是一个乘的是秘钥矩阵,一个乘的是秘钥矩阵的逆矩阵。


代码

# write by 2021/7/6
# 希尔密码
from math import sqrt
import numpy as np
from scipy import linalg
DIC = "abcdefghijklmnopqrstuvwxyz"
# 使用列表创建空矩阵, 用0填充
def create_matrix(n, m):
    matrix = []
    for i in range(n):
        matrix.append([])
        for j in range(m):
            matrix[i].append(0)
    # print(matrix)
    return matrix
# 输入矩阵
def input_matrix(matrix):
    n, m = len(matrix), len(matrix[0])
    for i in range(n):
        for j in range(m):
            matrix[i][j] = int(input(f"输入{i}行{j}列数据: "))
    return matrix
# 矩阵相乘
def matrix_multiply(matrix_a, matrix_b):
    a_n, a_m = len(matrix_a), len(matrix_a[0])
    b_n, b_m = len(matrix_b), len(matrix_b[0])
    if a_m != b_n:
        return -1
    matrix_c = create_matrix(a_n, b_m)
    num = 0
    for i in range(a_n):
        for j in range(b_m):
            num = 0
            for k in range(a_m):
                num += matrix_a[i][k]*matrix_b[k][j]
            matrix_c[i][j] = num
    return matrix_c
# 辗转相除法
def gcd(a, b):
    a, b = b, a % b
    # print(a, b)
    if b == 0:
        return a
    else:
        return gcd(a, b)
# 判断秘钥的行列式是否与26互质, 以及秘钥是否可逆
def judge_key(key):
    a = np.array(key)
    det = int(np.linalg.det(a))
    if det == 0:
        return 0
    if 26 > det:
        max_gcd = gcd(26, det)
    else:
        max_gcd = gcd(det, 26)
    # print(f"26,{det}最大公约数: ", max_gcd)
    if max_gcd == -1 or max_gcd == 1:
        return 1
    return 0
def encrypt_hill(string, key):
    # 判断秘钥的行列式是否与26互质, 以及秘钥是否可逆
    if not judge_key(key):
        return -1
    ciphertext = ""
    n = len(key)
    str_len = len(string)
    plaintext_lis = []
    ciphertext_lis = []
    # 转为数字
    for i in string.lower():
        if DIC.find(i) != -1:
            plaintext_lis.append(DIC.index(i)+1)
        else:
            return -1
    # 补"0"
    if str_len % n != 0:
        for i in range(n-len(plaintext_lis) % n):
            plaintext_lis.append(0)
    m = len(plaintext_lis)//n   # m 为新矩阵的列数
    # 转为列表形式矩阵
    plaintext_matrix = create_matrix(n, m)
    for i in range(m):
        for j in range(n):
            plaintext_matrix[j][i] = plaintext_lis[i*n+j]
    # print("原位置=", plaintext_matrix)
    matrix_key = np.matrix(np.array(key))
    matrix_plaintext = np.matrix(np.array(plaintext_matrix))
    matrix_c = matrix_key*matrix_plaintext
    ciphertext_lis = matrix_c.tolist()
    # print("加密后的位置=", ciphertext_lis)
    for i in range(m):
        for j in range(n):
            ciphertext += DIC[ciphertext_lis[j][i] % 26-1]
    # print("ciphertext=", ciphertext)
    return ciphertext
def decrypt_hill(string, key):
    # 判断矩阵行列式是否与26互质, 以及秘钥是否可逆
    if not judge_key(key):
        return -1
    plaintext = ""
    n = len(key)
    m = len(string)//n
    # inv_key = np.matrix(np.array(key)).I
    inv_key = linalg.inv(np.array(key))
    # print("原矩阵=", np.array(key))
    # print("逆矩阵=", inv_key)
    # print("乘积=", inv_key*np.array(key))
    ciphertext_matrix = create_matrix(n, m)
    # 注意:这里的矩阵是一列一列放置,并不是一行一行放置
    for i in range(m):
        for j in range(n):
            ciphertext_matrix[j][i] = DIC.index(string[i*n+j])+1
    # print("密文位置=", ciphertext_matrix)
    matrix_ciphertext = np.matrix(np.array(ciphertext_matrix))
    # print(f"{matrix_ciphertext}")
    matrix_c = inv_key*matrix_ciphertext
    ciphertext_lis = matrix_c.tolist()
    # print("解密后位置=", ciphertext_lis)
    for i in range(m):
        for j in range(n):
            # if ciphertext_lis[i][j] % 26 != 0:
            # print(round(ciphertext_lis[j][i]) % 26)
            plaintext += DIC[round(ciphertext_lis[j][i]) % 26 - 1]
    return plaintext
if __name__ == '__main__':
    key_ = [[1, 2], [0, 1]]
    # print(matrix_multiply(key_, inv_key))
    print(judge_key(key_))
    ciphertext_ = encrypt_hill("flagishillissoeapy", key_)
    # ciphertext_ = "dloguszijluswogany"
    plaintext_ = decrypt_hill(ciphertext_, key_)
    print(f"{plaintext_}: {ciphertext_}")
目录
相关文章
|
数据安全/隐私保护
CTF密码学·置换密码,栅栏密码,曲路密码
1.置换密码 置换密码(Permutation Cipher)又叫换位密码(Transposi-tionCipher),它根据一定的规则重新排列明文,以便打破明文的结构特性。置换密码的特点是保持明文的所有字符不变,只是利用置换打乱了明文字符的位置和次序
1566 1
CTF密码学·置换密码,栅栏密码,曲路密码
|
1月前
|
人工智能 自然语言处理 搜索推荐
《生成式引擎优化(GEO)服务商选择指南》:让AI大模型主动推荐你
GEO(生成式引擎优化)是针对AI生成式搜索引擎的优化策略,旨在让企业信息在AI回答中优先呈现,实现“无点击曝光”。与传统SEO不同,GEO强调语义理解、权威内容和结构化数据,提升品牌在AI推荐中的可见性与可信度。企业需关注GEO服务商的技术实力、行业匹配度、服务流程完整性等维度,确保优化效果。
482 0
|
11月前
|
机器学习/深度学习 移动开发 前端开发
解密 SSE,像 ChatGPT 一样返回流式响应
解密 SSE,像 ChatGPT 一样返回流式响应
624 1
|
9月前
|
算法 安全 数据安全/隐私保护
BUUCTF-[2019红帽杯]easyRE(Reverse逆向)
本文详细介绍了对一个无壳的64位ELF文件进行逆向分析的过程。首先通过IDA查找关键字符串定位主函数,然后逐步分析函数逻辑,包括读取输入、异或操作等。接着通过多次Base64解码和异或操作,最终得到了关键的flag。整个过程涉及数组寻址、条件判断和函数调用等技术细节,展示了CTF竞赛中常见的逆向工程技巧。最后附上了完整的Python代码实现,帮助读者理解和复现。
559 1
BUUCTF-[2019红帽杯]easyRE(Reverse逆向)
|
11月前
|
机器学习/深度学习 运维 监控
深度学习之视频内容理解
基于深度学习的视频内容理解(Video Content Understanding, VCU)是一项关键技术,旨在通过神经网络模型自动分析、解读和提取视频中的语义信息。
691 10
|
JSON JavaScript 前端开发
基于Vue+SpringBoot+MySQL实现个人博客系统
基于Vue+SpringBoot+MySQL实现个人博客系统
|
编解码 IDE API
ERA5逐时、逐日、逐月气象数据的手动下载与Python代码批量下载方法
ERA5逐时、逐日、逐月气象数据的手动下载与Python代码批量下载方法
2190 2
|
机器学习/深度学习 存储 算法
数据分类分级-结构化数据识别与分类的算法实践
本文分享了用九智汇数据分类分级产品开发过程中,对数据识别和数据分类中涉及的算法进行抽象、融合,以形成标准化产品所做的努力和积累的经验。当然,算法只是分类分级产品的一小部分,整个产品设计,工程实现,也是支撑标准化产品的关键,但是限于作者水平有限,本文只讨论算法相关的话题,欢迎大家关注公众号以了解更多信息。
314 1
|
算法 安全 前端开发
从零玩转前后端加解密之SM2
从零玩转前后端加解密之SM2
514 0
|
Java Spring
websocket @Autowired注入为null问题的解决办法
websocket @Autowired注入为null问题的解决办法