hill密码(希尔密码)
简述
希尔密码是利用矩阵进行加密的一种加密算法,其本质是一种多表代换密码。
- 百科:
希尔密码是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。
每个字母当作26进制数字:A=0, B=1, C=2… 一串字母当成n维向量,跟一个n×n的矩阵相乘,再将得出的结果模26。
注意用作加密的矩阵(即密匙)在 必须是可逆的,否则就不可能解码。只有矩阵的行列式和26互质,才是可逆的。
希尔密码由于采用矩阵运算加密,因此在相同的明文加密时,可能会出现不同的密文,因此可以很好的抵御字母频率攻击法。
加解密
- 加密:
1、定义一个矩阵a(须存在逆矩阵)作为加密密钥:
[1,2,1]
[0,2,1]
[1,0,2]
2、将需要加密的明文字母转换为其对应的字母表数字(1-a,2-b……);
3、将转换后的明文数字序列按照密钥矩阵的阶数进行分组(如本次为3个字符一组);
4、每组数字序列和密钥矩阵进行矩阵的乘法运算(1x3 矩阵乘以 3x3矩阵),结果即为密文数字序列;
5、可将密文数字序列转换为其对应字母,即为密文字符串。
- 解密:
解密流程与加密相同,唯一不同之处在于:需先求出加密密钥的逆矩阵
在做矩阵相成时,用密文分组乘以逆矩阵,结果即为明文
代码实现
#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time : 2019/12/11 14:53
# @Author : SystemDefenser
# @Email : mrwx1116@163.com
# @Software: PyCharmfrom numpy import linalg# 输入矩阵并判断是否存在逆矩阵
def inputMatrix():while True:# 输入一行、作为行列式的阶数和行列式的第一行rank = list(input("").split())matrix = [[0] * len(rank) for i in range(len(rank))]matrix[0] = rank# 输入行列式剩余数据for i in range(1, len(matrix)):matrix[i] = list(input("").split())# 判断每一行输入是否合法if len(matrix[i]) != len(matrix):print("输入有误,重新输入。")continue# 转换字符型为整型for i in range(len(matrix)):matrix[i] = list(map(lambda x: int(x), matrix[i]))# 判断是否存在逆矩阵if not judgeInverse(matrix):print("矩阵不存在逆矩阵,重新输入。")continuereturn matrix# 判断是否存在逆元
def judgeInverse(matrix):try:linalg.inv(matrix)except:return Falsereturn True# 生成密钥(矩阵的逆矩阵)
def createMatrixInverse(matrix):try:matrix_inverse = linalg.inv(matrix)except:return -1return matrix_inverse# 生成消息分组
def createMassageList(massage, matrix):matrixRank = len(matrix)massageList = []# 扩充消息序列并创建分组while len(massage) % matrixRank != 0:massage += " "for i in range(1, len(massage) + 1, matrixRank):massageList.append(massage[i-1:i + matrixRank - 1])return massageList# 字母序列转化为数字
def letterToDigit(massageList):massageDigitList = [] # 替换后的数字列表letterList = [] # 字母列表for i in range(ord("a"), ord("z") + 1):letterList.append(chr(i))for i in range(10):letterList.append(str(i))# 添加空格,解决分组填充问题letterList.append(" ")# 替换字母为数字for massage in massageList:listTmp = []for i in range(len(massage)):listTmp.append(letterList.index(massage[i]))massageDigitList.append(listTmp)return massageDigitList# 数字序列转化为字母
def digitToLetter(massageList):massageLetterList = [] # 还原后的字母列表letterList = []for i in range(ord("a"), ord("z") + 1):letterList.append(chr(i))for i in range(10):letterList.append(str(i))letterList.append(" ")# 替换数字为字母for massage in massageList:massageLetterList.append(letterList[massage % 37])return massageLetterList# 加密
def encrypt(massage, matrix):ciphertextList = [] # 加密结果列表massageList = createMassageList(massage, matrix)massageDigitList = letterToDigit(massageList)# 矩阵相乘for massageDigit in massageDigitList:for i in range(len(massageDigit)):sum = 0for j in range(len(massageDigit)):sum += massageDigit[j] * matrix[j][i % len(matrix)]ciphertextList.append(sum % 37)return ciphertextList# 解密
def decrypt(massage, matrix):plaintextList = [] # 解密结果列表matrix_inverse = createMatrixInverse(matrix)massageList = createMassageList(massage, matrix)# 矩阵相乘for msg in massageList:for i in range(len(msg)):sum = 0for j in range(len(msg)):sum += msg[j] * matrix_inverse[j][i % len(matrix)]plaintextList.append(sum % 37)# 浮点型转换为整型(采用四舍五入——round())plaintextList = list(map(lambda x: int(round(x)), plaintextList))plaintextList = digitToLetter(plaintextList) # 数字转换为字母plaintext = ""for item in plaintextList:plaintext += itemreturn plaintextif __name__ == "__main__":while True:print("—————希尔密码—————")choice = input("1、加密 2、解密\n请选择:")if choice == "1":print("输入矩阵:")matrix = inputMatrix()massage = input("输入msg:")massageList = createMassageList(massage, matrix)ciphertextList = encrypt(massage, matrix)print("加密结果:", ciphertextList)elif choice == "2":massageList = list(map(int, list(input("输入密文序列:").split(","))))print("输入矩阵:")matrix = inputMatrix()matrix_inverse = createMatrixInverse(matrix)print("逆矩阵:")for item in matrix_inverse:print(item)plaintext = decrypt(massageList, matrix)print("解密结果:", plaintext)
其中,求逆矩阵部分未能手算,调用了numpy库中的linalg函数,惭愧………………
加密测试
—————希尔密码—————
1、加密 2、解密
请选择:1
输入矩阵:
1 0 1 1
0 1 0 1
1 1 0 0
1 1 0 1
输入msg:systemdefenser
加密结果: [18, 24, 18, 24, 11, 19, 4, 20, 36, 35, 5, 27, 2, 15, 4, 20]
—————希尔密码—————
1、加密 2、解密
请选择:2
输入密文序列:18, 24, 18, 24, 11, 19, 4, 20, 36, 35, 5, 27, 2, 15, 4, 20
输入矩阵:
1 0 1 1
0 1 0 1
1 1 0 0
1 1 0 1
逆矩阵:
[ 0. -1. 0. 1.]
[ 0. 1. 1. -1.]
[ 1. 1. 1. -2.]
[ 0. 0. -1. 1.]
解密结果: systemdefenser
- 加密:
- 解密:
部分代码详解
- 输入矩阵部分
代码片段:
while True:# 输入一行、作为行列式的阶数和行列式的第一行rank = list(input("").split())matrix = [[0] * len(rank) for i in range(len(rank))]matrix[0] = rank# 输入行列式剩余数据for i in range(1, len(matrix)):matrix[i] = list(input("").split())# 判断每一行输入是否合法if len(matrix[i]) != len(matrix):print("输入有误,重新输入。")continue
该片段位于 inputMatrix() 函数中。
输入矩阵部分未让用户先定义阶数,而是通过用户输入的矩阵第一行,来决定本次迷药矩阵的阶数,并且不断进行合法判断。
- 解密部分
代码片段:
# 浮点型转换为整型(采用四舍五入——round())plaintextList = list(map(lambda x: int(round(x)), plaintextList))plaintextList = digitToLetter(plaintextList) # 数字转换为字母
该片段位于 decrypt(massage, matrix) 函数中。
由于逆矩阵存在不可约分或整除的小数,因此在此处采用四舍五入round(x) 的方法不严谨地解决此问题。
hill密码(希尔密码)相关推荐
- Hill Cipher 希尔密码 已知明文密文 求秘钥方法
Hill Cipher,已知明文密文,求秘钥 设K为秘钥, 为明文字母对应的数字矩阵, 为密文字母对应的数字矩阵. 是希尔加密的过程. 为了求解K,我们需要求解P的膜26逆元. 注意,这里是膜26逆元 ...
- Visual Studio 2019下用 C# 实现 Hill2 二阶希尔密码 的加密、解密 GUI界面
1.什么是Hill2 什么是Hill密码 希尔密码(Hill)使用每个字母在字母表中的顺序作为其对应的数字,即 A=0,B=1,C=2 等,然后将明文转化为 n 维向量,跟一个 n × n 的矩阵相乘 ...
- C++希尔密码Hill Cipher算法(附完整源码)
希尔密码Hill Cipher的算法 希尔密码(Hill Cipher) 的算法的完整源码(定义,实现,main函数测试) 希尔密码(Hill Cipher) 的算法的完整源码(定义,实现,main函 ...
- 08:vigenère密码_密码技术:Vigenére密码,Playfair密码,Hill密码
08:vigenère密码 1)Vigenére密码 (1) Vigenére Cipher) This technique is an example of Polyalphabetic Subst ...
- C++希尔密码的实现以及运用
希尔密码(Hill Cipher)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=0, B=1, C=2... 一串字母当成n维向量,跟一 ...
- 希尔密码在CTF中应用—记一道题
CTF-crypto 解题思路来自:i春秋的大佬们 https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=52687&highli ...
- JavaScript实现希尔密码 算法(附完 整源码)
JavaScript实现希尔密码 算法 Matrix.js完整源代码 hillCipher.js完整源代码 hillCipher.test.js完整源代码 Matrix.js完整源代码 export ...
- linux 正则 设置密码复杂度,Ubuntu修改密码及密码复杂度策略设置方法
一.修改密码 1.修改普通用户密码 passwd 先输入当前密码确认,然后输入新的密码修改 2.修改root用户密码 sudo passwd root 默认root用户被禁止登录,如果需要解除限制,修 ...
- shell批量创建和删除10个系统帐号密码(密码为随机10位字符串)
1.添加10个用户和密码,并把账号和密码保存到指定的文件里 # vim create_user.sh #/bin/bash # for jiangjj in {1..10}; do if id use ...
- php 挂马 密码123456,admin密码-常用密码加密md5值,123456,admin,admin888
一 : 常用密码加密md5值,123456,admin,admin888 123456这个经md5算法加密之后是多少? 16位:49ba59abbe56e057 32位:e10adc3949ba59a ...
最新文章
- 摇滚吧HTML5!Jsonic超声波前端交互!
- 如何使用Fiddler调试线上JS代码(转自:http://www.cnblogs.com/RockLi/p/3511132.html)
- js 面向对象例子
- 合格网络管理员需了解的主要职责
- 《C++ Primer 第五版》(第6.3~6.7节)——返回指向数组/函数的指针,函数重载,默认形参、inline函数和constexpr函数
- 这些行为,属于学术不端!
- 像搭“乐高”一样实现整合式网络安全体系
- 这才是男朋友该说的话^_^
- jetty java 禁用目录列表_Apache httpd 目录列表禁用配置(options indexes)
- Dell Inspiron 3443 BIOS升级问题解决
- 不错的Unity教程
- 关闭Word提示无法将更改后的内容保存到共用模板
- 使用PhantomJS网页截图
- 背景图页面缩小会变形_CSS背景图拉伸不变形
- 1、定义一个复数类Complex,使得下面的代码能够工作。 Complex c1(3,5); Complex c2=4.5; c1.add(c2); c1.show();
- JVM内存分哪几个区,每个区的作用是什么?
- linux hwclock -r显示的HWC TIME(硬件时钟时间)与timedatectl结果中的RTC TIME(实时时钟时间)有什么区别?BIOS时钟源
- 2022-2028全球超声波封管机行业调研及趋势分析报告
- 一款mipi转lvds的lcd调试(lt8912b)
- 计算机毕业设计Java家电产品售后(源码+系统+mysql数据库+lw文档)