“Hill的加密與解密”
Hill加密是另一種多字母代替密碼,與多表代替密碼不同的是,Hill密碼要求将明文分成同等規模的若幹個分組(最後一個分組涉及到填充),每一個分組被整體的加密代換,即希爾密碼屬于分組加密。Hill密碼的算法思想是:将一個分組中的d個連續的明文字母通過線性變換轉換為d個密文字母。這種變換由d個線性方程決定,其中每個字母被配置設定一個數值(0,1,。。。,25)。解密隻需要做一次逆變換就可以了,密鑰就是變換矩陣本身。
設明文為一維矩陣m,密文為一維矩陣c,密鑰用k矩陣表示,則:
即密文分組=明文分組*密鑰矩陣。
本程式使用的密鑰是:
下面是具體的源程式:—頭檔案:classical.h
#pragma once
//古典密碼之希爾加密
#include <math.h>
#include <string.h>
#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 < ROW; i++) //1*4的行列式與4*4的行列式相乘
{
for (int j = 0; j < COL; 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 < ROW; k1++)
{
for (int k2 = 0; k2 < COL; k2++)
{
if (k1 < i && k2 < j)
{
arr[k1][k2] = *(*(K + k1) + k2);
}
else if (k1 < i && k2 > 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 < j)
{
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 < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
bag = fun(i, j, K) / (det);
if (bag < 0)
{
ptr[j][i] = (26 + bag) % (26);
}
else
{
ptr[j][i] = bag % (26);
}
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; 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 < strlen(ptr); 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 < ROW; i++)
{
num[i] = *(pnum + i);
}
parr = plus(K, num);
for (int j = 0; j < ROW; j++)
{
printf("%c", *(parr+j) + 'A');
}
pnum = pnum + ROW;
}
printf("\n");
free(parr);
break;
case 2:
pln = inputsecret();
for (int i = 0; i < strlen(pln); 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 < ROW; i++)
{
num[i] = *(pnum + i);
}
parr = answer(K, num, det);
for (int j = 0; j < ROW; 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 <stdio.h>
#include <stdlib.h>
#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加密:
Hill解密: