仿射算法加解密


一、仿射密碼加密

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM