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";
	}
}

我是一定会回私信的兔子~