Hill密码(希尔密码)
希尔密码可以防止频率分析攻击(因为运用的是矩阵,可能密文中同一个字母翻译成明文是不一样的)
- 希尔密码隐藏了单字母的频率
- 字母和数字的对应可以修改成其他方案
- 抵抗频率攻击
- 易受已知明文的攻击
希尔密码的加密过程:
1.准备一个n*n的可逆矩阵 E(即密钥)
2.将a-z 对应0-25编码
3.将要加密的一串字母当作n维度向量,比如矩阵E的大小是3*3,那么abcde就可以分为 abc de 转为数字就是012 340(不足n位补0)
4.密文(数字列向量)=(E*明文(数字列向量) )mod26
5.得到密文(字母)
希尔密码的解密:
1.算出E的逆矩阵E-1
2.明文(数字列向量)(E-1*密文(数字列向量))mod26
3.得到明文(字母)
下面是代码的实现(使用了自己写的Matrix类,其中大部分方法在本例中没有使用),代码中有较为详尽的注释
package HillEncryp;
import link_about.KeyInput;
public class HillEncryp {
static double[][] encry={ //建立密钥矩阵要用的二维数组
{6,24,1},
{13,16,10},
{20,17,15}
};
static double[][] de_encry={ //建立密钥矩阵的逆矩阵的二维数组
{8,5,10},
{21,8,21},
{21,12,8}
};
static Matrix m_encry=new Matrix(encry); //密钥矩阵
static Matrix m_de_encry=new Matrix(de_encry);//密钥矩阵的逆矩阵
public static void main(String[] args) {
int t = 0;
while (true) {
System.out.print("1.Hill密码程序\n0.exit");
t = KeyInput.readInt();
if(t==0)
break;
Hill();//
}
}
public static double[][] set_matrix_plaintext(String s){//设置明文矩阵
double[][] plain=new double[3][3];
int k=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(k<s.length()){
plain[j][i]=s.charAt(k)-97;
k++;
}
else {
plain[j][i]=0;
}
}
}
return plain;
}
public static String de_encry_matrix(Matrix matrix){//将矩阵中内容转为字符串
String s="";
for(int i=0;i<3;i++) {
for (int j = 0; j < 3; j++) {
s += (char) (matrix.getData(j, i) + 97); //注意此处用j,i是因为明文和密文都是按列向量保存的
}
}
return s;
}
public static void Hill(){
System.out.println("请输入要加密的字符串(最好在6-9个字符内)");
String s=KeyInput.readString();
String s1="";
String s2="";
double[][] plain=set_matrix_plaintext(s);//构建两个矩阵
Matrix m_plain=new Matrix(plain);
double[][] cipher=new double[3][3];
Matrix m_cipher=new Matrix(cipher);
m_cipher=m_encry.multiply(m_plain);//加密
System.out.println("\n密钥为\n"+m_encry.toString());
System.out.println("\n明文矩阵为:\n"+m_plain);
System.out.println("\n初始密文矩阵为:\n"+m_cipher.toString());
m_cipher.matrix_mod(26);
System.out.println("\n密文矩阵为:\n"+m_cipher);
s1=de_encry_matrix(m_cipher);//根据密文矩阵得到密文
System.out.println("\n密文为:\n"+s1);
System.out.println("\n密钥的逆矩阵为:\n"+m_de_encry);
Matrix decode=m_de_encry.multiply(m_cipher);//密钥的逆矩阵和密文矩阵相乘,再mod26获得解密后的矩阵
decode.matrix_mod(26);
System.out.println("\n解密得矩阵为:\n"+decode.toString());
s2=de_encry_matrix(decode);
System.out.println("\n解密得到明文:\n"+s2);
}
}
package HillEncryp;
public class Matrix {
private int rows;
private int cols;
double data[][];
private Matrix(){
this(new double[1][1]);
}
public Matrix(int rows,int cols){ //设置矩阵的行和列
//double data[][]=new double[rows][cols];//行和列
try {
if(rows>0&&cols>0) {
this.data=new double[rows][cols];
this.rows=rows;
this.cols=cols;
}
else
throw new IllegalArgumentException();
}
catch(Exception e){
System.out.println(e.toString());
}
}
public Matrix(double data[][]){
this.rows=data.length;
this.cols=data[0].length;
this.data=(double[][])data.clone();
}
public boolean setData(double[][] matrix){//给整个矩阵赋值
this.data=matrix.clone();
return true;
}
public void matrix_mod(int mod){//将矩阵除以一个数取余
for(int i=0;i<data.length;i++){
for(int j=0;j<data[0].length;j++){
this.data[i][j]%=mod;
}
}
}
public boolean setData(int row,int col,double value) {
row--;
col--;
try {
if(row>=0&&col>=0) {
this.data[row][col] = value;
return true;
}
else {
throw new IllegalIndexException();
}
}
catch (Exception e) {
System.out.println(e.toString());
// TODO: handle exception
}
return false;
}
public double getData(int row, int col){ //获取指定位置的值
try {
if(row>=0&&col>=0)
return this.data[row][col];
else {
throw new IllegalIndexException();
}
}
catch (Exception e) {
System.out.println(e.toString());
// TODO: handle exception
}
return (Double) null;
}
public Matrix multiply(Matrix m){ //矩阵乘法 如果不明白则应该复习一下线性代数
Matrix ki=new Matrix(m.getCols(),m.getRows());
try {
if(m.cols==this.rows&&m.rows==this.cols) {
int x1,y1,k1;
for(x1=0;x1<this.rows;x1++)
for(y1=0;y1<this.cols;y1++)
for(k1=0;k1<this.cols;k1++)
ki.data[x1][y1]+=this.data[x1][k1]*m.data[k1][y1];
}
else
throw new MatrixMultiplicationException();
}
catch (Exception e) {
System.out.println(e.toString());
}
return ki;
}
private String MatrixtoString(int row,int col,String x){//辅助重写tostring的
if(col==0)
return x+"["+this.data[row][col]+",";
if(col<this.cols-1)
return x+this.data[row][col]+",";
return x+this.data[row][col]+"]\n";
}
public String toString(){//控制台输出矩阵
int k=0;
int i=0;
String xk=new String();
for (k=0;k<this.rows;k++)
for( i=0;i<this.cols;i++)
xk=MatrixtoString(k,i,xk);
return xk;
}
public boolean equal(Object obj){
if(this==obj)
return true;
if(obj==null)
return false;
if(obj instanceof Matrix){
Matrix p=(Matrix)obj;
if(p.toString()==this.toString())
return true;
}
return false;
}
public int getRows() {
return this.rows;
}
public int getCols() {
return this.cols;
}
}
package HillEncryp;
public class IllegalArgumentException extends Exception{
public String toString() {
return "The Arguments are wrong";
}
}
package HillEncryp;
import java.lang.Exception;
public class IllegalIndexException extends Exception{
/**
*
*/
public String toString() {
return "The row or col is wrong";
}
}
package HillEncryp;
public class MatrixMultiplicationException extends Exception {
public String toString() {
return "cant Multiple them";
}
}
我是一定会回私信的兔子~