/**
* 由密文根据映射表转换为二维向量
* @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"。
-->