古典密码(Hill加密算法)

“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解密:

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

时间: 2024-10-05 16:47:09

古典密码(Hill加密算法)的相关文章

密码学基础知识(三)古典密码

说完了前面那些,想起个事,本系列依据内容主要来自<现代密码学>马春光编著.我就是学这本书的. 好了,古典密码就是古时候的密码,哈哈,逗你玩的,shannon的保密系统的通信理论发表前的都是古典密码,会在密码学简史中介绍这位牛人的. 学习古典密码学的意义:学习设计原理和分析方法 古典密码也是,俩门派:置换和代换,顾名思义,一个是换了个原来有的,一个是换了个原来没有的.学术点讲就是前者明文和密文空间一样,后者 不一样.你要是问我啥是明文空间和密文空间啊,我就呵呵.是M 和 C.m明文的集合,c密文

1.密码学概念及古典密码

一.前言 信息安全面临的威胁无处不在,多为人为威胁,也就是对信息的人为攻击,人为攻击可分为被动攻击和主动攻击. 被动攻击:即为窃听,分为两类:一类是消息内容获取:另一类是业务流分析,如获取消息的格式,长度及位置等敏感信息.该攻击因为对消息没有做出变动,难以检测,所以被动攻击重点在于预防而不是检测. 主动攻击:为对数据流的改动或产生假的数据流,分为三类:①中断,对系统可用性进行攻击,如破坏管理系统等:②篡改,对系统的完整性攻击,如修改传送的消息内容等:③伪造,对系统真实性攻击,如插入伪造的消息.

古典密码

古典密码是对字母间相互代替或相互换位来进行加密.分代替密码和换位密码两种. 代替指将明文中的字符用其它字符代替,分单表代替和多表代替.代替方案称为秘钥. 单表代替密码的安全性不高,一个原因是一个明文字母只由一个密文字母代替.可以利用频率分析来破译. 多表代换密码,即构造多个密文字母表,在密钥的控制下用以一系列代换表依次对明文消息的字母序列进行代换. Playfair密码,用密钥控制生成矩阵,然后每两个字符为单位进行代换.若相邻字符相同要插入一个特殊的字符隔开,若最终字符数为奇数也要填充一个特殊的

【转载】古典密码

题目:密文内容如下{79 67 85 123 67 70 84 69 76 88 79 85 89 68 69 67 84 78 71 65 72 79 72 82 78 70 73 69 78 77 125 73 79 84 65}请对其进行解密提示:1.加解密方法就在谜面中         2.利用key值的固定结构 答案:CTF{COULDYOUEXCHANGETHEINFORMATION}分析:将Ascii码转换为字母,得到OCU{CFTELXOUYDECTNGAHOHRNFIENM}I

古典密码简介

从密码学发展历程来看,可分为古典密码(以字符为基本加密单元的密码)以及现代密码(以信息块为基本加密单元的密码)两类.而古典密码有着悠久的历史,从古代一直到计算机出现以前,古典密码学主要有两大基本方法: ①置换密码(又称易位密码):明文的字母保持相同,但顺序被打乱了. ②代替密码:就是将明文的字符替换为密文中的另一种的字符,接收者只要对密文做反向替换就可以恢复出明文. 古典密码是密码学的根源,虽然都比较简单而且容易破译,但研究古典密码的设计原理和分析方法对于理解.分析以及设计现代密码技术是十分有益

古典密码-多表密码体制

如果明文中不同的位置的同一明文字母在密文中对应的密文字母不同,则称为多表密码体制. 代表性的多表密码: 1.Vigenere密码 2.Beaufort密码 3.running-key密码 4.Vernam密码 5.Hill密码 例子: 1.Vigenere密码加密: 设明文   m=m1m2...mn 密钥      k = k1k2...kn 则密文   c=Ek(m)=c1c2...cn 其中      ci=(mi+ki)(mod 26),(i=1,2,...,n) Vigenere密码解

重写AgileEAS.NET SOA 中间件平台账号密码的加密算法

一.平台简介 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市场快速变化的开发团队,以达到节省开发成本.缩短开发时间,快速适应市场变化的目的. AgileEAS.NET SOA中间件平台提供了敏捷快速开发软件工程的最佳实践,通过提供大量的基础支撑功能如IOC.ORM.SOA.分布式体系及敏捷并发开发方法所支撑的插件开发体系,以及提供了大量的实体.数据模型设

古典密码-单表密码体制

如果明文中不同的位置的同一明文字母在密文中对应的密文字母相同,则称其为单表密码体制. 代表性的单表密码: 1.移位或加法密码 2.乘数或乘法密码 3.仿射密码 4.密钥短语密码 下面分别举一个例子: 1.加法密码算法: P=C=K=Zm   (Zm∈{0,1,...,m-1}) Ek(x)=x+k(mod m)=y∈C Dk(y)=y-k(mod m)=x∈P 当k=3时,该密码算法就是凯撒密码. E3(1)=1+3(mod 26)=4   1代表A,4代表D,所以就把明文A加密成D D3(4)

密码学补充学习简记之古典密码

1 密码体制 2 代替密码 2.1 代替密码的定义和分类 2.2 代替密码的构造 1.构造单表代替密码的关键是构造一张明密代替表. 2.代替表构造方法:密码字法.洗牌法.仿射法.广义仿射法. 1.多表代替密码的构造可分为底表的构造和密钥序列的构造. 2.底表必须为拉丁方阵. 3.密钥的构造方法:主观密钥序列(一本书).客观密钥序列.伪随机密钥序列. 3 移位密码 3.1 移位密码的定义和分类 3.2 移位密码的构造 移位密码的构造可归结为n元置换的构造,置换的构造与代替表的构造类似. 4 乘积密