累死人之希尔加密

#include <iostream>
#include <vector>
#include<string.h>
#include<stdio.h>
#define N 5
using namespace std;

int exgcd(int A,int &x,int B,int &y)
{
    int x1,y1,x0,y0;
    x0=1;y0=0;
    x1=0;y1=1;
    int r=(A%B+B)%B;
    int q=(A-r)/B;
    x=0;y=1;
    while(r)
    {
        x=x0-q*x1;
        y=y0-q*y1;
        x0=x1;
        y0=y1;
        x1=x;y1=y;
        A=B;B=r;r=A%B;
        q=(A-r)/B;
    }
    return B;
}
int modq(int a,int n,int x,int y)
{
int b=1;
   int d=exgcd(a,x,n,y);
        if(b%d==0)
        {
            x=(x%(n/d)+n/d)%(n/d);
            if(!x)x++;
            return x;
        }
        else printf("Not Exist\n");
}
//计算矩阵的行列式 
int getA(int A[N][N],int n)
{
    if(n==1)   return A[0][0];
    int num=0;
    int temp[N][N]={0.0};
    int i,j,k;
    for(i=0;i<n;i++)
        {
            for(j=0;j<n-1;j++)
                {
                    for(k=0;k<n-1;k++)
                    {
                        if(k>=i)   temp[j][k]=A[j+1][k+1];
                        else       temp[j][k]=A[j+1][k];
                    }
                }
            int t=getA(temp,n-1);
            if(i%2==0)  num+=A[0][i]*t;
            else        num-=A[0][i]*t;
            }
    return num%26;
}
//求矩阵的伴随矩阵 
void getAstart(int A[N][N],int n,int newA[N][N]) 
{
    if(n==1)
    {
        newA[0][0]=1;
        return;
    }
    int i,j,k,t;
    int temp[N][N];
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            for(k=0;k<n-1;k++)
            {
                for(t=0;t<n-1;t++)
                {
                    temp[k][t]=A[(k>=i)?k+1:k][(t>=j)? t+1:t];
                }
            }
            newA[j][i]=(getA(temp,n-1));
            if((i+j)%2==1)  newA[j][i]=-newA[j][i];
            newA[j][i]=newA[j][i]%26;
            if(newA[j][i]<0)  newA[j][i]=(newA[j][i]+26)%26;
        }
    }
}
//求矩阵的逆
void  getInverse(int A[N][N],int n,int I[N][N])
{
    int t[N][N]={0.0};
    int flag=getA(A,n);
    int x,y;
    int e=modq(flag,26,x,y);
    if(e==0)  return;
    else
    {
        getAstart(A,n,t);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                I[i][j]=(t[i][j]*e)%26;
                if(I[i][j]<0)  
                    I[i][j]=(I[i][j]+26)%26;
            }
        }
    }
} 

int gcd(int m,int n)
{
    int r=0;
    if(m==0||n==0)  return 0;
    if(m==1||n==1)  return 1;
    else
    {
        if(n>m)
        {
            int s=m;
            m=n;n=s;
        }    
    r=m%n;
    while(r!=0)
    {
        m=n;
        n=r;
        r=m%n;
        if(r==0)
            {
                return n;
            }
        }
    }
}

bool IsInverse(int A[N][N],int n)//判断矩阵是否可作为密钥 
{
    int t=getA(A,n);
    if(gcd(t,26)==1)  return true;
    else   return false;
}
vector<int> change1(string s) //将明文密文转化为字母表中的次序,A为0,依次类推 
 {
  vector<int>v;
  for(int i=0;i<s.size();i++)
  {
  if(s[i]>='A'&&s[i]<='Z')
  v.push_back(s[i]-'A');
  if(s[i]>='a'&&s[i]<='z')
  v.push_back(s[i]-'a');
}
return v;
 }

 string change2(vector<int>v)//将字母的次序转化为小写字母 
 {
  string s="";
  for(int i=0;i<v.size();i++) 
  {
  char a=v[i]+97;
  s+=a;
}
return s;
 }
 string change3(vector<int>v)//将字母的次序转化为大写字母 
 {
  string s="";
  for(int i=0;i<v.size();i++) 
  {
  char a=v[i]+65;
  s+=a;
}
return s;
 }
 
//对明文进行加密
void addcode(int A[N][N],string s){
    int length=s.length();
    vector<int> mingnum;
    mingnum=change1(s);
    int rows=length/N;
    int lines=N;
    int mingmatrix[rows][lines]={0.0};
    for(int i=0;i<length;i++){
        mingmatrix[i/5][i%5]=mingnum[i];
    }
    int mimatrix[rows][lines]={0.0};
    for(int i=0;i<rows;i++){
        for(int j=0;j<lines;j++){
            int temp=0;
            for(int k=0;k<lines;k++){
                temp+=mingmatrix[i][k]*A[k][j];
            }
            mimatrix[i][j]=temp%26;
        }    
    }
    vector<int> minum;
    for(int i=0;i<rows;i++){
        for(int j=0;j<lines;j++){
            minum.push_back(mimatrix[i][j]);
        }
    }
    string miwen=change2(minum);
    cout<<"得到的密文"<<miwen<<endl;    
} 

void deaddcode(int A[N][N],string s){
    int D[N][N]={0.0};
    getInverse(A,5,D);
    int length=s.length();
    vector<int> minum;
    minum=change1(s);
    int rows=length/N;
    int lines=N;
    int mimatrix[rows][lines]={0.0};
    for(int i=0;i<length;i++){
        mimatrix[i/5][i%5]=minum[i];
    }
    int mingmatrix[rows][lines]={0.0};
    for(int i=0;i<rows;i++){
        for(int j=0;j<lines;j++){
            int temp=0;
            for(int k=0;k<lines;k++){
                temp+=mimatrix[i][k]*D[k][j];
            }
            mingmatrix[i][j]=temp%26;
        }    
    }
    vector<int> mingnum;
    for(int i=0;i<rows;i++){
        for(int j=0;j<lines;j++){
            mingnum.push_back(mingmatrix[i][j]);
        }
    }
    string mingwen=change2(mingnum);
    cout<<"得到的明文"<<mingwen<<endl;    
} 
 
 
 
int main()
{

    cout<<"请输入一个5阶密钥矩阵"<<endl;
    int ars[5][5];
    for(int i=0;i<5;i++){
        cout<<""<<i+1<<""<<endl; 
        for(int j=0;j<5;j++){
            cin>>ars[i][j];
        }
    }
    
    cout<<"请输入明文"<<endl;
    string mess;
    cin>>mess;
    addcode(ars,mess);
    
    cout<<"请输入密文"<<endl;
    string code;
    cin>>code;
    deaddcode(ars,code);
} 

其实老师让做的是变长的,我找了网上的代码,加密解密和它做的略有不同,不过除非是希尔加密否则求行列式不推荐这种做法,因为循环到了三层以上代码的可读性非常差,但是用这种方法求行列式的好处就是比较简单,推荐传一个二级指针进去进行行列式求解,较好理解,但对于希尔加密不适合,因为会在判断互素的时候损失精度。

posted @ 2019-03-26 15:43  daremosiranaihana  阅读(386)  评论(0编辑  收藏  举报