天天看点

仿射加密(java)

仿射加密的加密过程是一个线性变换:

在仿射加密中,可设0-25对应 'a '-‘z’ 这26个字母。

  • 设y为密文,x为明文,则:

    y(x)=(k1x+k2) mod 26

    并且要求gcd(k1,26)=1;(即k1与26的最大公约数为1)

    要求k1和26互素,不然y(x)就不是一个单射函数

    在求解仿射解密函数时,需要求k1在Z26上的乘法逆元a-1∈Z26,这可由扩展欧几里得算法求解

    解密 x=( (k1-1)(y(x)-k2) )%26

    下面是仿射加密的java实现:(附有注释)

    • KeyInput只是一个辅助类,用来控制台输入,完全可以用scanner代替
    • 本程序假设只输入a-z这26个字母

      扩展的欧几里得算法:

    26=a1*q1+c1; //注意 第一次的a1是我们加密过程中的k1

    a1=a2*q2+c2; //a2=c1;

    a2=a3*q3+c3; //a3=c2;

    · · · · · · //直到cj==1时停止

    b-1=0;

    b0=1;

    bj=(-1)*bj-1*qj+bj-2 //当cj==1时求出bj

    k3=bj%26 //k3是解密时需要的数

    ``

    package AffineEncryp;
    
    import link_about.KeyInput;
    
    public class AffineEncryp {
        static int k1,k2,k3;
    
        public static void main(String[] args) {
            int t=0;
            while(true){
                System.out.println("1.仿射加密程序 \n0.exit");
                t= KeyInput.readInt();
                if(t==0) {
                    break;
                }
                AffineEncryption();
            }
        }
    
        public static char affine(char c){//加密
            int c1=c-97;
            int c2=(c1*k1+k2)%26;//加密过程就是将字母从0-25编码,然后进行函数变化得到另一个字母
            return (char)(c2+97);
        }
    
        public static char de_affine(char c){//解密
            int m=(k3*((int)c-97)-((k3*k2))%26);//解密过程运用解密函数,其中的k3要用扩展的欧几里得算法得出,
            if(m<0){//此处判断m是否为0是因为当m为负数的时候无法按照算法的要求进行mod运算,否则会出错
                m+=26;
            }
            c=(char)((m%26)+97);
            return c;
        }
    
        public static void AffineEncryption(){
            System.out.println("请给定两个参数k1,k2");
             k1=KeyInput.readInt();
             k2=KeyInput.readInt();
            while( new Gcd().gcd(k1,k2)!=1){
                System.out.println("映射不唯一,请重新给定k1,k2");
                 k1=KeyInput.readInt();
                 k2=KeyInput.readInt();
            }
            k3=new ExtenedEuclid().get_k(k1,26);//计算k3
            System.out.println("ps:k3的值为"+k3 +"");
            System.out.println("请输入要加密的字符串");
            String s=KeyInput.readString();
            String s1="";
            for(char c:s.toCharArray()){//加密
                s1+=affine(c);
            }
            System.out.println("加密后字符串为");
            System.out.println(s1);
            System.out.println("解密:");
            for(char c:s1.toCharArray()){
                System.out.print(de_affine(c));
            }
            System.out.println();
            return;
        }
    }
    
               

    ``

    ``

    package AffineEncryp;
    
    public class ExtenedEuclid {//扩展的欧几里得算法
        public int get_k(int a,int mod){
            if(a==1){
                return 1;
            }
            int[] b=new int[99];
            int c=mod%a;
            int q=mod/a;
            b[0]=0;
            b[1]=1;
            for(int i=2;;i++){//从2开始,事实上这个位置可以优化,只需要一个长度为3的数组就可以,为了方便理解我这里没有进行优化
                b[i] = (-1) * q * b[i - 1] + b[i - 2];
                if(c==1){
                    if(b[i]<0)//同样的道理,如果按照标准算法直接进行mod运算会出错,所以改成 '+'
                        return b[i]+mod;
                    else
                        return b[i]%mod;
                }
                q = a / c;
                int c1 = c;
                c = a % c;
                a = c1;
            }
        }
    }
    
               
    ``

``

package AffineEncryp;

public class Gcd {
    public  int gcd(int a,int b){//求最大公约数
        int gcd=0;
        if(a<b){//确保a更大,否则交换a、b的值
            a+=b;
            b=a-b;
            a-=b;
        }
        if(a%b==0){ //直接相除没有余数,且a>b,说明b即是最大公约数
            return b;
        }
        while(a%b>0){//否则就辗转相除,再重复上面的过程,直到二者相等,此时 a%b==0一定成立,a==b==最大公约数
            a=a%b;
            if(a<b){
                a+=b;
                b=a-b;
                a-=b;
            }
            if(a%b==0){
                return b;
            }
        }
        return gcd;
    }
}

           

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