Hill密码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hill密码相关的知识,希望对你有一定的参考价值。

希尔密码(Hill Password)是运用基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。每个字母当作26进制数字:A=0, B=1, C=2... 一串字母当成n维向量,跟一个n×n的矩阵相乘,再将得出的结果MOD26。注意用作加密的矩阵(即密匙)在\mathbb_^n必须是可逆的,否则就不可能译码。只有矩阵的行列式和26互质,才是可逆的

#include<stdio.h>  
#include<string.h>
#include<ctype.h>
#include<stdlib.h>

int A[1000][1000];//转化矩阵
int a[1000][1000];//单位矩阵[A E]
int B[1000][1000];//矩阵的逆矩阵A^(-1)
int ming[1000][1000];//明文矩阵
int mi[1000][1000];//密文矩阵
int n;//矩阵的阶数
void input()//输入数据
{
    int i, j;
    for( i = 1; i <= n; i++ )
        for( j = 1; j <= n; j++ )
            A[i][j] = rand() % 26;
    memcpy( a, A, sizeof( A ) );//将矩阵A复制给a
    for( i = 1; i <= n; i++ )//将矩阵变成[a E]的形式,E为单位矩阵
    {
        for( j = n + 1; j <= 2*n; j++ )
        {
            if( i + n == j )
                a[i][j] = 1;
            else
                a[i][j] = 0;
        }
    }
}

void output()     //输出函数
{
    int i,j;
    printf("矩阵A的元素\n");
    for( i = 1; i <= n; i++ )
    {
        for( j = 1; j <= n; j++ ){
            printf("%d ",A[i][j]);
        }
        printf("\n");
    }
    printf("A矩阵的逆矩阵B为\n");
    for( i = 1; i <= n; i++ )//输出A矩阵的逆矩阵B
    {
        for( j = 1; j <= n; j++ )
        {
            B[i][j] = a[i][j+n];
            printf("%d ",B[i][j]);

        }
        printf("\n");
    }
}

int Extend_Gcd( int a, int b, int &x, int &y )//扩展欧几里得算法
{
    if( b == 0 )
    {
        x = 1;
        y = 0;
        return a;
    }
    int r = Extend_Gcd( b, a % b, x, y );
    int t = x;
    x = y;
    y = t - a / b * y;
    return r;
}

int ni( int a)//求逆a*x=1(mod n)
{
    int x, y;
    int d = Extend_Gcd( a, 26, x, y );
    if( d == 1 )
        return ( x % 26 + 26 ) % 26;
    else
        return -1;
}

int gaosi()//高斯-约当消元求A矩阵的逆矩阵B
{
    int i, j, k;
    for( k = 1; k <= n; k++ )//高斯-约当消元
    {
        int Ni = ni( a[k][k] );
        if( Ni == -1 ) return 0;
        for( i = k + 1; i <= 2 * n; i++ )
            a[k][i] = ( a[k][i] *  Ni % 26 + 26 ) % 26;
        for( i = 1; i <= n; i++ )
        {
            if( i == k ) continue;
            for( j = k + 1; j <= 2 * n; j++ )
                a[i][j] = ( ( a[i][j] - a[i][k] * a[k][j] % 26 ) % 26 + 26 ) % 26;
        }
    }
    return 1;
}

void jiami()    //加密过程
{
    int i, j, k;
    char mingstr[100];
    char mingc;
   
    printf("请输入明文");
    scanf("%s",&mingstr);
    int len = strlen( mingstr );
    if( len % n )
    {
        for( i = len; i < len/n*n+n; i++)
            mingstr[i] = a;
        mingstr[i] = \0;
    }
    puts( mingstr );
    int Len = strlen( mingstr );
    for( i = 1; i <= Len/n; i++ )//将明文分成len/n段
    {
        for( j = 1; j <= n; j++ )//求每一段的明文转换为矩阵
        {
            if( mingstr[(i-1)*n+j-1] >= a && mingstr[(i-1)*n+j-1] <= z )
                ming[i][j] = mingstr[(i-1)*n+j-1] - a;
            else
                ming[i][j] = mingstr[(i-1)*n+j-1] - A;
        }
    }
    for( k = 1; k <= Len/n; k++ )//求len/n段的密文矩阵
    {
        for( i = 1; i <= n; i++ )//利用矩阵的乘法
        {
            mi[k][i] = 0;
            for( j = 1; j <= n; j++ )
                mi[k][i] = ( mi[k][i] + ming[k][j] * A[j][i] % 26 + 26 ) % 26;
        }
    }
    printf("密文为");
    for( i = 1; i <= Len/n; i++ )//输出密文
    {
        for( j = 1; j <= n; j++ )
        {
            mingc = mi[i][j] + A;
           
            printf("%c",mingc);
        }
       
    }
    printf("\n");
}

void jiemi()   //解密过程
{
    int i, j, k;
    char mistr[100];
    char mingc;
    printf("请输入密文");
    scanf("%s",&mistr);
    int len = strlen( mistr );
    for( i = 1; i <= len/n; i++ )//将密文分成len/n段
    {
        for( j = 1; j <= n; j++ )//求每一段的密文转换为矩阵
        {
            if( mistr[(i-1)*n+j-1] >= a && mistr[(i-1)*n+j-1] <= z )
                mi[i][j] = mistr[(i-1)*n+j-1] - a;
            else
                mi[i][j] = mistr[(i-1)*n+j-1] - A;
        }
    }
    for( k = 1; k <= len/n; k++ )//求len/n段的明文矩阵
    {
        for( i = 1; i <= n; i++ )//利用矩阵的乘法
        {
            ming[k][i] = 0;
            for( j = 1; j <= n; j++ )
                ming[k][i] = ( ming[k][i] + mi[k][j] * B[j][i] % 26 + 26 ) % 26;
        }
    }
    printf("明文为");
    for( i = 1; i <= len/n; i++ )//输出明文
    {
        for( j = 1; j <= n; j++ )
        {
            mingc = ming[i][j] + A;
    
            printf("%c",mingc);
        }
       
    }
    printf("\n");
   
}


int main()
{  
int flag;
    do{ 
        printf( "1.加密2.解密3.退出\n");
        scanf("%d",&flag);
        if(flag==1)
        {printf("请输入加密矩阵的阶数n:");
        scanf("%d",&n);
        do{
            input();//数据输入
        }while( !gaosi() );
         output();
         jiami();}//加密过程
        else if(flag==2)
        {jiemi();//解密过程
        }
        else if(flag!=1&&flag!=2&&flag!=3) printf("输入错误,请重新输入!\n");
    }while(flag!=3);
      return 0;
}

 

以上是关于Hill密码的主要内容,如果未能解决你的问题,请参考以下文章

Hill密码

信息安全-2:python之hill密码算法[原创]

信息安全-2:python之hill密码算法[原创]

古典密码(Hill加密算法)

Visual Studio 2019下用 C# 实现 Hill2 二阶希尔密码 的加密解密 GUI界面

密码学——几种典型的古典密码体制(Caesar体制Playfair体制Vigenere体制Beaufort体制以及Hill体制)