仿射加密的加密过程是一个线性变换:
在仿射加密中,可设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;
}
}