一、仿射密碼加密
仿射密碼
仿射密碼也是一般單表替代密碼的一個特例,是一種線性變換。仿射密碼的明文空間和密文空間與移位密碼相同,但密鑰空間為 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; }