天天看點

古典密碼(Hill加密算法)

      “Hill的加密與解密” 

古典密碼(Hill加密算法)

       Hill加密是另一種多字母代替密碼,與多表代替密碼不同的是,Hill密碼要求将明文分成同等規模的若幹個分組(最後一個分組涉及到填充),每一個分組被整體的加密代換,即希爾密碼屬于分組加密。Hill密碼的算法思想是:将一個分組中的d個連續的明文字母通過線性變換轉換為d個密文字母。這種變換由d個線性方程決定,其中每個字母被配置設定一個數值(0,1,。。。,25)。解密隻需要做一次逆變換就可以了,密鑰就是變換矩陣本身。

       設明文為一維矩陣m,密文為一維矩陣c,密鑰用k矩陣表示,則:

古典密碼(Hill加密算法)

即密文分組=明文分組*密鑰矩陣。

       本程式使用的密鑰是:

古典密碼(Hill加密算法)
      下面是具體的源程式:

—頭檔案: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加密算法)

       Hill解密:

古典密碼(Hill加密算法)