Hill密码(希尔密码)

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

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

你可能感兴趣的:(数据结构与算法,密码学,信息安全,线性代数)