hill密码源代码c语言,古典密码(Hill加密算法)(示例代码)

“Hill的加密与解密”

fa3bdf3e10c7a54cb1a3cb46f81a7dfc.png

Hill加密是另一种多字母代替密码,与多表代替密码不同的是,Hill密码要求将明文分成同等规模的若干个分组(最后一个分组涉及到填充),每一个分组被整体的加密代换,即希尔密码属于分组加密。Hill密码的算法思想是:将一个分组中的d个连续的明文字母通过线性变换转换为d个密文字母。这种变换由d个线性方程决定,其中每个字母被分配一个数值(0,1,。。。,25)。解密只需要做一次逆变换就可以了,密钥就是变换矩阵本身。

设明文为一维矩阵m,密文为一维矩阵c,密钥用k矩阵表示,则:

e2b1942bd43cdc098cca5aaf099aeb0f.png

即密文分组=明文分组*密钥矩阵。

本程序使用的密钥是:

2816d6dbe8fece9e0675b471beac6818.png

下面是具体的源程序:—头文件:classical.h

#pragma once

//古典密码之希尔加密

#include 

#include 

#define ROW 4    //行

#define COL 4     //列

int* plus(int(*K)[COL], int * num)     //进行加密

{

int *arr = (int *)calloc(sizeof(int),4);

int sum = 0;

int sub = 0;

for (int i = 0; i 

{

for (int j = 0; j 

{

sum = (*(num + j)) * (*(*(K + j) + i));

sub = sub + sum;

}

arr[i] = (arr[i] + sub) % 26;

sub = 0;

}

return arr;

}

int fun(int i, int j, int(*K)[COL])       //求伴随矩阵

{

int num = 0;

int arr[ROW][COL] = { 0 };

int left = 0;

int right = 0;

for (int k1 = 0; k1 

{

for (int k2 = 0; k2 

{

if (k1 

{

arr[k1][k2] = *(*(K + k1) + k2);

}

else if (k1  j)

{

arr[k1][k2 - 1] = *(*(K + k1) + k2);

}

else if (k1 > i && k2 > j)

{

arr[k1 - 1][k2 - 1] = *(*(K + k1) + k2);

}

else if (k1 > i && k2 

{

arr[k1 - 1][k2] = *(*(K + k1) + k2);

}

}

}

left = arr[1][1] * arr[2][2] * arr[0][0] + arr[0][1] * arr[1][2] * arr[2][0]

+ arr[1][0] * arr[2][1] * arr[0][2];

right = arr[0][2] * arr[1][1] * arr[2][0] + arr[0][1] * arr[1][0] * arr[2][2]

+ arr[0][0] * arr[1][2] * arr[2][1];

num = pow((double)(-1), (i + 1) + (j + 1)) * (left - right);

return num;

}

int* answer(int(*K)[COL], int * str, int det)      //希尔解密

{

int ptr[ROW][COL] = { 0 };     //ptr为逆矩阵

int* ans = (int *)calloc(sizeof(int), 4);

int sum = 0;

int sub = 0;

int bag = 0;

for (int i = 0; i 

{

for (int j = 0; j 

{

bag = fun(i, j, K) / (det);

if (bag 

{

ptr[j][i] = (26 + bag) % (26);

}

else

{

ptr[j][i] = bag % (26);

}

}

}

for (int i = 0; i 

{

for (int j = 0; j 

{

sum = (*(str + j)) * ptr[j][i];

sub = sub + sum;

}

ans[i] = (ans[i] + sub) % 26;

sub = 0;

}

return ans;

}

void menu()      //菜单

{

printf("      ——古典密码          \n\n");

printf("**********   1.加密    *******\n");

printf("**********   2.解密    *******\n");

printf("**********   0:退出    *******\n");

printf("请选择:");

}

char* inputclear()       //输入明文

{

printf("请输入明文:");

char num[20] = {‘\n‘};

char *ptr = num;

int i = 0;

char ch;

fflush(stdin);      //清除缓冲区

while ((ch = getchar()) != ‘\n‘)

{

num[i] = ch;

i++;

}

return ptr;

}

char* inputsecret()       //输入密文

{

printf("请输入密文:");

char num[20] = { ‘\n‘ };

char *ptr = num;

int i = 0;

char ch;

fflush(stdin);      //清除缓冲区

while ((ch = getchar()) != ‘\n‘)

{

num[i] = ch;

i++;

}

return ptr;

}

void judge(int n, int(*K)[4])     //处理加密或解密

{

char *ptr, *pln;

int src[20];

int num[4] = { 0 };

int *parr = NULL;

int *pnum = NULL;

int det = -1;     //计算K的行列式的值

switch (n)

{

case 1:                                 //加密

ptr = inputclear();

for (int i = 0; i 

{

if (*ptr != ‘\n‘ && *ptr != EOF)

{

src[i] = *(ptr + i) - ‘A‘;

}

else

{

break;

}

}

printf("加密后得到的密文:");

pnum = src;

while (*pnum >= 0 && *pnum <= 25)

{

for (int i = 0; i 

{

num[i] = *(pnum + i);

}

parr = plus(K, num);

for (int j = 0; j 

{

printf("%c", *(parr+j) + ‘A‘);

}

pnum = pnum + ROW;

}

printf("\n");

free(parr);

break;

case 2:

pln = inputsecret();

for (int i = 0; i 

{

if (*pln != ‘\n‘ && *pln != EOF)

{

src[i] = *(pln + i) - ‘A‘;

}

else

{

break;

}

}

printf("解密后得到的明文:");

pnum = src;

while (*pnum >= 0 && *pnum <= 25)

{

for (int i = 0; i 

{

num[i] = *(pnum + i);

}

parr = answer(K, num, det);

for (int j = 0; j 

{

printf("%c", *(parr + j) + ‘A‘);

}

pnum = pnum + ROW;

}

printf("\n");

free(parr);

break;

case 0:

exit(EXIT_FAILURE);

default:

break;

}

}

—源文件:test.cpp

#define _CRT_SECURE_NO_WARNINGS 1

//希尔加密

#include 

#include 

#include "classical.h"

int main()

{

int K[4][4] = { { 8, 6, 9, 5 }, { 6, 9, 5, 10 }, { 5, 8, 4, 9 }, { 10, 6, 11, 4 } };   //密钥

int left=K[0][0] * K[1][1] * K[2][2] * K[3][3] + K[1][0] * K[0][3] * K[3][2] * K[2][1]+ K[2][0] * K[3][1] * K[0][2] * K[1][3] + K[3][0] * K[0][1] * K[1][2] * K[2][3];

int right = K[0][3] * K[1][2] * K[2][1] * K[3][0] + K[0][0] * K[1][3] * K[2][2] *

K[3][1]+ K[0][1] * K[1][0] * K[2][3] * K[3][2] + K[0][2] * K[1][1] * K[2][0] * K[3][3];

int n = 0;

menu();

scanf("%d", &n);

judge(n, K);

system("pause");

return 0;

}

—运行结果:

Hill加密:

eb42044603c94d066230ed68ef719d38.png

Hill解密:

36c0e79bc33ae23dd07da65bb9061d92.png

很明显,Hill密码将解密的长消息分组,分组的长度取决于密钥矩阵的维数,Hill密码的强度在于完全隐藏了单字母的频率。字母和数字的对应也可以更改为其他的方案,使得不容易攻击成功。一般来说,对抗仅有密文的攻击强度较高,但易受到已知明文攻击。

本文出自 “无心的执着” 博客,谢绝转载!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值