Hill密码是一种传统的密码体系。加密原理:选择一个二阶可逆整数矩阵A称为密码的加密矩阵,也就是这个加密体系的密钥。加密过程:

  明文字母依次逐对分组,例如加密矩阵为二阶矩阵,明文就两个字母一组,如果最后一组不足(明文长度为奇数),就补充任意字母凑个双,构成二维向量组a。计算矩阵A乘以向量组a,得到新的二维列向量b,反查字母表得到两个字母即为密文字母。

  也就是说,加密过程为:明文-->映射为数字矩阵-->经过矩阵加密-->映射为字符串(密文)

解密过程也是同样的过程,只不过中间使用矩阵解密,Hill密码是一种传统的密码体系。

根据这个过程,每一阶段功能代码如下:

首先创建一个类,HillCrypto,

成员变量有加密密钥矩阵和解密密钥矩阵,字母转数值映射和数值转字母映射

初始化阶段,实例化以上成员变量,其中映射表较大,因此写在了本地文件中便于重用,创建映射时需要读取本地文件。

文件内容如下:

代码如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; public class HillCrypto { private Map<Character, Integer> table;
private Map<Integer, Character> getPlainMap; private int[][] encryption = {{1, 1},{0, 3}};
private int[][] decryption; public HillCrypto(String tableFilePath) {
// TODO Auto-generated constructor stub
int mrow = encryption.length;int mcolumn = encryption[0].length;
this.decryption = new int[mrow][mcolumn]; // 二阶矩阵的逆矩阵,如果是更高阶的,使用其他办法,比如通过余子式除以行列式得到逆矩阵,行列式的求法见鄙人的其他博客。
decryption[0][0] = (encryption[1][1] * 27 / (encryption[0][0]*encryption[1][1] - encryption[0][1]*encryption[1][0])) % 26;
decryption[0][1] = - (encryption[0][1] * 27 / (encryption[0][0]*encryption[1][1] - encryption[0][1]*encryption[1][0])) % 26;
decryption[1][0] = - (encryption[1][0] * 27 / (encryption[0][0]*encryption[1][1] - encryption[0][1]*encryption[1][0])) % 26;
decryption[1][1] = (encryption[0][0] * 27 / (encryption[0][0]*encryption[1][1] - encryption[0][1]*encryption[1][0])) % 26;
// 该算法的所有矩阵在求出之后都需要取余数
for (int i = 0; i < decryption.length; i++) {
for (int j = 0; j < decryption[0].length; j++) {
if (decryption[i][j] < 0) {
decryption[i][j] += 26;
}
}
}
this.print(decryption);
this.table = this.readFile(tableFilePath);
this.getPlainMap = this.mapReverse(table); } private void print(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
System.out.print(matrix[i][j]+", ");
}
System.out.println();
}
} // map的键值互换
private Map<Integer, Character> mapReverse(Map<Character, Integer> table){
Iterator<Character> it = table.keySet().iterator();
Map<Integer, Character> result = new HashMap<Integer, Character>();
while (it.hasNext()) {
Character character = (Character) it.next();
result.put(table.get(character), character);
}
return result;
} /**
* 从本地读取一个文件以创建字母值表,例如A->0, B->1,...,Z->25
* @param tableFilePath
* @return
*/
private Map<Character, Integer> readFile(String tableFilePath) {
File file = new File(tableFilePath);
FileReader fr;
Map<Character, Integer> map = new HashMap<Character, Integer>();
try {
fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String line = "";
String[] kv = null;
while ((line = br.readLine())!= null) {
kv = line.split(",");
// System.out.println("读取键值对:<"+kv[0]+", "+kv[1]+">");
map.put(kv[0].charAt(0), Integer.parseInt(kv[1]));
}
br.close();
fr.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
}

密文是字符串,需要根据所读取的映射表,两两一组转换为数字矩阵:

    /**
* 由密文根据映射表转换为二维向量
* @return
*/
private int[][] getVectorFromString(String text){
int textLength = text.length();
// System.out.println("密文长度为:" + textLength);
int row = textLength;
if (row % 2 != 0) {
row = (row + 1) / 2;
int column = this.encryption.length;
int[][] vector = new int[row][column];
for (int i = 0; i < row-1; i++) {
for (int j = 0; j < column; j++) {
vector[i][j] = this.table.get(text.charAt(i*column + j));
}
}
vector[row-1][column-2] = this.table.get(text.charAt((row-1)*column + column-2));
// this.print(vector);
vector[row-1][column-1] = this.table.get('A');
return this.transpose(vector);
}else {
row = row / 2;
int column = this.encryption.length;
int[][] vector = new int[row][column];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
vector[i][j] = this.table.get(text.charAt(i*column + j));
}
}
return this.transpose(vector);
}
} // 求矩阵转置
public int[][] transpose(int[][] matrix){
int row = matrix.length;
int column = matrix[0].length;
int[][] newmatrix = new int[column][row];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
newmatrix[j][i] = matrix[i][j];
}
}
return newmatrix;
}

加密或者解密都需要用到矩阵乘法

    // 求矩阵乘以向量的结果
public int[][] transform(int[][] matrix, int[][] vector) {
int mrow = matrix.length;
int mcolumn = matrix[0].length;
int column = vector[0].length;
int[][] result = new int[mcolumn][column];
for (int k = 0; k < column; k++) {
for (int i = 0; i < mcolumn; i++) {
for (int j = 0; j < mrow; j++) {
result[i][k] += matrix[i][j] * vector[j][k];
// System.out.printf("result[%d][%d] = %d\n", i, k, result[i][k]);
}
}
}
for (int i = 0; i < mcolumn; i++) {
for (int j = 0; j < column; j++) {
result[i][j] %= 26;
}
}
return result;
}

从数字矩阵中反查映射表得到字符串

    public char[] getPlain(int[][] table) {
int row = table.length;
int column = table[0].length;
char[] plaintext = new char[row*column];
for (int i = 0; i < column; i++) {
for (int j = 0; j < row; j++) {
plaintext[i*row+j] = this.getPlainMap.get(table[j][i]);
}
}
return plaintext;
}

然后用一个实例演示加密然后解密的过程:

    public static void main(String[] args) {
String tableFilePath = "src/zhaoke/table.csv";
// 加密密钥 String originPlain = "JAVAISTHEBESTLANGUAGEINTHEWORLD";
System.out.println("明文:"+originPlain); HillCrypto hc = new HillCrypto(tableFilePath);
// 加密过程
// 首先字符串映射为数值
int[][] plainNum = hc.getVectorFromString(originPlain);
// hc.print(plainNum);
// 然后用加密矩阵进行加密
int[][] encryptedPlain = hc.transform(hc.encryption, plainNum);
// 然后映射为字符串就是密文了
String cipherPlain = new String(hc.getPlain(encryptedPlain));
System.out.println("加密后的密文"+cipherPlain); // 解密过程
// 首先映射为数值
int[][] cipherNum = hc.getVectorFromString(cipherPlain);
// hc.print(cipherNum);
// 使用解密矩阵进行解密
int[][] newtable = hc.transform(hc.decryption, cipherNum);
// 然后映射为明文
String plainText = new String(hc.getPlain(newtable));
System.out.println("解密所得明文为: "+plainText);
}

执行结果:

明文:JAVAISTHEBESTLANGUAGEINTHEWORLD
加密后的密文KCWCBEBXGFXEFJOPBKHUNAHHMOLSDJEC
解密所得明文为: JAVAISTHEBESTLANGUAGEINTHEWORLDA

  可以看到结果正确,说明算法是有效的,至于为什么最终会多出一个A,那是因为明文长度是奇数,为了能映射为二维向量需要凑整,查表阶段加上了一个随机字母凑双因此多了一个A,但是这不影响我们能看出明文就是"Java is the best language in the world"。

Hill密码解密过程(Java)的更多相关文章

  1. 信息安全-2:python之hill密码算法[原创]

    转发注明出处:http://www.cnblogs.com/0zcl/p/6106513.html 前言: hill密码算法我打算简要介绍就好,加密矩阵我用教材上的3*3矩阵,只做了加密,解密没有做, ...

  2. Hill密码

    希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明.每个字母当作26进制数字:A=, B=, C=... 一串字母当成n维向量,跟一个 ...

  3. Java Base64加密、解密原理Java代码

    Java Base64加密.解密原理Java代码 转自:http://blog.csdn.net/songylwq/article/details/7578905 Base64是什么: Base64是 ...

  4. https原理:证书传递、验证和数据加密、解密过程解析

    写的太好了,就是我一直想找的内容,看了这个对https立马明白多了 http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html 我们都知 ...

  5. 转载:https原理:证书传递、验证和数据加密、解密过程解析

    写的太好了,就是我一直想找的内容,看了这个对https立马明白多了 http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html 我们都知 ...

  6. https 证书传递、验证和数据加密、解密过程解析

    我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议. HTTPS简介 HTTPS其实是有两部分组成:HTTP + SSL ...

  7. https加解密过程

    前前后后,看了许多次关于https加解密过程的相关文档资料,一直似懂非懂.这次,终于理解了,还画了个图,做个记录. 知识点 1.对称加密:双方用同一个密码加解密.如des,aes 2.非对称加密:双方 ...

  8. 转: https原理:证书传递、验证和数据加密、解密过程解析

    原本连接:http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html 我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取.所以很 ...

  9. Python实现AES的CBC模式加密和解密过程详解 和 chr() 函数 和 s[a:b:c] 和函数lambda

    1.chr()函数 chr() 用一个范围在 range(256)内的(就是0-255)整数作参数,返回一个对应的字符. 2.s[a:b:c] s=(1,2,3,4,5) 1>. s[a]下标访 ...

随机推荐

  1. weblogic 安装+部署(一)

    昨天刚接触weblogic,在windows下搭建了一个weblogic,没什么技术,留个笔记. 1.首先要有jdk,添加环境变量这个没什么好说的. 2.下载weblogic:可以去官网下:http: ...

  2. 【题解】[USACO12MAR]Cows in a Skyscraper G

    题目链接 题目大意:给定一个集合\(S\),给一个限制条件\(P\),要求划分集合,使得每一个子集\(A\in S\),\(A\)满足限制条件\(P\),且划分总数最小. 注意到数据范围\(n< ...

  3. 【从零开始撸一个App】Kotlin

    工欲善其事必先利其器.像我们从零开始撸一个App的话,选择最合适的语言是首要任务.如果你跟我一样对Java蹒跚的步态和僵硬的语法颇感无奈,那么Kotlin在很大程度上不会令你失望.虽然为了符合JVM规 ...

  4. 2016年 实验三 B2C模拟实验

    实验三 B2C模拟实验 [实验目的] 掌握网上购物的基本流程和B2C平台的运营 [实验条件] ⑴.个人计算机一台 ⑵.计算机通过局域网形式接入互联网. (3).奥派电子商务应用软件 [知识准备] 本实 ...

  5. mysql 登陆与退出

    Mysql登陆与退出 登陆参数 登陆命令 mysql -uroot -p 回车输入密码 退出有三个命令:  exit  quit  \q 修改mysql提示符 连接mysql客户端时通过参数指定: 登 ...

  6. go mod模式,引入自己的包,goland飘红

  7. nginx安全:配置ssl证书(https证书)

    一,配置https证书的意义 https协议是由SSL+http协议构建的安全协议,支持加密传输和身份认证, 安全性比http要更好,因为数据的加密传输,更能保证数据的安全性和完整性 例如:不使用ht ...

  8. Harbor 安装教程

    Harbor 安装教程 一. CentOS设置 1. 更换阿里源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com ...

  9. 监听MySQL的binlog日志工具分析:Canal

    Canal是阿里巴巴旗下的一款开源项目,利用Java开发.主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费,目前主要支持MySQL. GitHub地址:https://github. ...

  10. origin把点图和线图放在一起

    首先分别做好点图和线图在两个graph中,然后选中其中一副图(点图或者线图),然后按下图选择: 如果有多个图,可以在弹出窗口中选择多个sheet.