仿射算法加解密
一、仿射密码加密
仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 K={(k1,k2)| k1,k2∈Z26,gcd(k1,26)=1}
对任意m∈M,c∈C,k = (k1,k2)∈K。
定义加密变换为:c = Ek (m) = (k1 m +k2) (mod 26)
相应解密变换为: m = Dk (c) = k1-1 (c-k2) (mod 26)
实例:
设明文消息为china,密钥k=(k1, k2)=(9,2)试用仿射密码对其进行加密。
明文消息对应的数字序列为(2,7,8,13,0),用仿射密码对明文进行加密如下:
故加密后的密文为:unwpc。
加密代码实现
#include<stdio.h> #include <string.h> int k1,k2; char text[50]; //加密函数 void encrypt() { int i,z=0; int l = strlen(text); for(i=0;i<l;i++) { //判断大小写 if (text[i] >= 'A' && text[i] <= 'Z'){ text[z]=(k1*(text[i]-'A')+k2)%26+'A'; } else if (text[i] >= 'a' && text[i] <= 'z'){ text[z]=(k1*(text[i]-'a')+k2)%26+'a'; } else{ //判断是否是空格 text[z] = text[i]; } z++; } printf("密文为:%s\n",text); } int main(void) { printf("输入明文\n"); scanf("%[^\n]%*c", text); printf("请输入密钥k1\n"); scanf("%d",&k1); printf("请输入密钥k2\n"); scanf("%d",&k2); encrypt(); getchar(); return 0; }
二、仿射密码解密
仿射密码
仿射密码也是一般单表替代密码的一个特例,是一种线性变换。仿射密码的明文空间和密文空间与移位密码相同,但密钥空间为 K={(k1,k2)| k1,k2∈Z26,gcd(k1,26)=1} ,其中,, 。
对任意m∈M,c∈C,k = (k1,k2)∈K,
定义加密变换为:c = Ek (m) = k1 m +k2 (mod 26)
相应解密变换为:m = Dk (c) = k1-1 (c-k2) (mod 26)
示例1:
密文消息为unwpc,密钥k=(k1, k2)=(9,2),试对密文消息进行解密。解密过程如下:
密文消息对应的数字为(20,13,22,15,2),利用扩展的欧几里德算法可计算出,k1的逆元为3
故恢复出来的明文为china。
代码实现
#include<stdio.h> #include <string.h> int k1,k2; char text[100]; int *p;//第1行数组的值 int *q;//第二行数组的值 int h[2][10]; int degree; //解密函数 void decrypt() { int i,mid; int l = strlen(text); for(i=0;i<l;i++) { //判断大小写 if (text[i] >= 'A' && text[i] <= 'Z') { mid=text[i]-'A'-k2; text[i]=(k1*((text[i]-'A')-k2))%26+'A'; if(mid < 0) { text[i] = text[i] + 26; }//当k2过大,可能会出现负数 } else if (text[i] >= 'a' && text[i] <= 'z') { mid=(text[i]-'a')-k2; text[i]=(k1*((text[i]-'a')-k2))%26+'a'; if((mid)<0) { text[i]=text[i]+26; } } } printf("明文为:%s\n",text); } /*欧几里得算法*/ int gcd(int a,int b,int num) { *(p+num)=a; *(q+num)=b; num=num+1; if(b==0) return a; return gcd(b,a%b,num); } //扩展欧几里得求逆元 int vid(int x,int y) { int mid=0; mid=y; //求每次的y值 y=x-(h[0][degree]/h[1][degree])*y; x=mid; degree--; if(degree==-1) return x; return vid(x,y); } int inverse_element(int a) { int b,min; int num=0; b=26; //用两个指针指向a,b两个数。 p=&h[0][0]; q=&h[1][0]; //执行辗转相除法 min=gcd(a,b,num); //判断最大公约数是否为1 if(min==1) printf("%d,%d互素",a,b); else{ printf("%d,%d不互素",a,b); return 0; } //得到数组中最后一个数 for (degree = 0; degree <10 ; ++degree) { //a的值 if(*(p+degree)==1) break; } degree--; //进入求逆元的递归函数 int x=1,y=0; x=vid(x,y); //判断逆元 if(x>=0){ printf("\n逆元为%d",x); return x; } else{ printf("\n逆元为%d ",h[1][0]+x); return h[1][0]+x; } } int main(void) { printf("输入密文\n"); scanf("%[^\n]%*c", text); printf("请输入密钥k1\n"); scanf("%d",&k1); printf("请输入密钥k2\n"); scanf("%d",&k2); k1=inverse_element(k1);//获得逆元 decrypt(); return 0; }