Hill 加密算法

Hill 密码简介

Hill 密码是一种多字母代替密码。
Hill 密码要求首先将明文分成同等规模的若干个分组(最后一个分组不足时需要填充),每一个分组被整体加密变换,即 Hill 密码属于分组加密

Hill 密码算法的基本思想

每一个分组中的 d 个连续的明文字母通过线性变换(与密钥矩阵相乘),转换为 d个密文字母。

  • 明文: m=m1m2md
  • 密文: c=c1c2cd

其中,

  • c1=k11m1+k21m2++kd1md(mod26)
  • c2=k12m1+k22m2++kd2md(mod26)
  • cd=k1dm1+k2dm2++kddmd(mod26)

写成矩阵形式:

  • (c1,c2,cd)=(m1,m2,md)k11kd1k12kd2k1dkdd(mod26)

即:密文分组 = 明文分组 X 密钥分组。

例:

用 Hill 密码加密明文 “Pay more money”,密钥是:

172121718252119

解:

明文 “Pay more money” 可编码为 15 0 24 12 14 17 4 12 14 13 4 24;(共4组)
计算:

151241301412424171424172121718252119(mod26)=17121015172203111187

故对应的密文为:RRLMWBKASPDH。

具体实现

#include <iostream>
#include <cstring>
#include <cstdlib>
#define N 100
using namespace std;

//按第一列展开,递归计算行列式值 
int caluDet(int n, int **a)
{
    int i, r, c, p, q;
    int sum=0;
    if(n==1) 
        return a[0][0];
    int **det = (int**)malloc((n-1)*sizeof(int*));
    for(i=0; i<(n-1); i++)  
        det[i] = (int*)malloc((n-1)*sizeof(int));
    for(i=0; i<n; i++) {
        for(r=0; r<n-1; r++) {         //子矩阵 (n-1) 行
            if(r<i) p = 0;              //当前行 a[r] 赋值给子矩阵
            else    p = 1;             //下一行 a[r+1] 赋值给子矩阵
            for(c=0; c<n-1; c++)        //子矩阵 (n-1) 列
                det[r][c] = a[r+p][c+1]; 
        }
        if(i%2==0) q = 1;               //由于是对第一列展开,即 [i][0]
        else q = -1;
        sum = sum + a[i][0] * q*caluDet(n-1,det);
    }
    for(i=0; i<(n-1); i++)  
        free(det[i]); 
    free(det);
    return sum;
}

//初始化明文
void initPlain(char p[], int n)
{
    int i, len, t;
    cout << "输入明文p: \n";
    getchar(); gets(p);
    for(i=0; i<strlen(p); i++) {  
        if (p[i] ==' ')             //跳过空格 
            strcpy(p+i,p+i+1); 
        if (p[i]>='a' && p[i]<='z')  //小写转大写 
            p[i] -= 32; 
    }
    len = strlen(p); 
    t = len%n>0 ? n-len%n : len%n;
    while(t--)     //若最后一个明文对字母不足,则添加与最后一个明文相同的字母 
        p[strlen(p)] = p[len-1]; 
    p[strlen(p)] = '\0';
    cout <<"\nInit P: " << p << endl;   
}

//输入密钥矩阵
void keyMatrix(int **det, int len)
{
    int i, j;
    for(i=0; i<len; i++)  
        for(j=0; j<len; j++) 
            cin >> det[i][j]; 
}

//分组、矩阵乘法
void matricMultiply(char p[], char c[], int **key, int n) 
{
    int i,j,k;
    int len = strlen(p);
    for(i=0; i<strlen(p)/n; i++){       //明文每 n 个作为一行 
        for(j=0; j<n; j++){             //明文的列、密钥矩阵的列 
            for(k=0; k<n; k++){         //密钥矩阵的行 
                c[n*i+j] += ((p[n*i+k]-'A') * key[k][j]) % 26;
            }
            c[n*i+j] = c[n*i+j] % 26 + 'A'; 
            //cout << (int)c[n*i+j] << " ";
        }
    }
    cout << "Cipher: " << c << endl;    
}

int main()
{
    int i, j, n, len;
    char p[N]={0}, c[N]={0};
    cout << "输入密钥的阶:\n";
    cin >> n;
    //为密钥矩阵申请内存空间 
    int **key = (int**)malloc(n*sizeof(int*));
    for(i=0; i<n; i++) 
        key[i] = (int*)malloc(n*sizeof(int)); 
    //获取密钥矩阵并验证是否可逆 
    cout << "输入" <<n<<"阶密钥矩阵:\n";
    keyMatrix(key,n);   
    while(!caluDet(n, key)) {
        cout << "密钥不存在逆矩阵! 请重新输入:\n";
        keyMatrix(key,n);
    } 
    //初始化明文 
    initPlain(p, n);
    len = strlen(p); 
    //各组明文乘密钥矩阵加密
    matricMultiply (p, c, key, n);
    //释放密钥矩阵的内存空间 
    for(i=0; i<n; i++)  
        free(key[i]); 
    free(key);
    return 0;
}

测试结果

《Hill 加密算法》

    原文作者:维吉尼亚加密问题
    原文地址: https://blog.csdn.net/qq_25968195/article/details/70343972
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞