Hill密码资料
- 格式:ppt
- 大小:338.50 KB
- 文档页数:28


hill密码算法摘要:1.Hill 密码的概述2.Hill 密码的加密过程3.Hill 密码的解密过程4.Hill 密码的优缺点5.Hill 密码的应用案例正文:1.Hill 密码的概述Hill 密码是一种基于替换的密码算法,由英国密码学家George Hill 在1929 年提出。
它是一种对称密钥密码,意味着加密和解密所使用的密钥是相同的。
Hill 密码的主要特点是加密过程中,明文中的每个字符都会被替换为按照一定规则重新排列的字符。
2.Hill 密码的加密过程在加密过程中,Hill 密码采用了以下步骤:a.选择一个与明文长度相同的密钥。
b.将明文分成长度为n 的块,其中n 是密钥的长度。
c.对每个块中的字符进行重新排序,根据密钥中的对应字符进行替换。
具体来说,如果密钥中的第i 个字符是a,那么明文中的第i 个字符就用a 替换;如果密钥中的第i 个字符是b,那么明文中的第i 个字符就用b 替换,以此类推。
d.将加密后的块按照顺序拼接起来,得到加密后的密文。
3.Hill 密码的解密过程Hill 密码的解密过程与加密过程正好相反。
首先,将密文分成长度为n 的块,然后根据密钥中的字符对每个块中的字符进行还原。
最后,将还原后的块按照顺序拼接起来,得到解密后的明文。
4.Hill 密码的优缺点Hill 密码的优点是加密过程简单,易于实现。
然而,它也存在一些缺点:a.密钥长度决定了加密效果。
如果密钥长度较短,那么加密效果会受到较大影响。
b.容易受到字频分析的攻击。
因为Hill 密码的加密过程是基于字符替换,所以如果攻击者知道明文中字符的出现频率,就可以根据这些信息推测出密钥,从而破解密码。
5.Hill 密码的应用案例尽管Hill 密码存在一些缺点,但它仍然在某些场景下被使用。
例如,在早期的计算机网络中,由于计算能力有限,Hill 密码作为一种简单易行的加密方法被广泛应用。
希尔密码(Hill Cipher)简介: 希尔密码是基于矩阵的线性变换, 希尔密码相对于前面介绍的移位密码以及放射密码而言, 其最大的好处就是隐藏了字符的频率信息, 使得传统的通过字频来破译密文的方法失效.安全性: 希尔密码不是足够安全的, 如今已被证实, 关于希尔密码的破解不在本文范围内, 有兴趣的朋友可以研读相关书籍以了解相关破译方法.希尔密码所需要掌握的前置知识:1) 线性代数基础知识.2) 初等数论基础知识.坦白来说, 大部分密码学都要用到线性代数以及初等数论中的知识, 所以我希望大家可以自行找来相关书籍完成基础知识的学习, 所以关于什么是矩阵,什么是单位矩阵我不打算细讲. 在希尔密码中, 具体的话, 会涉及到矩阵的运算, 及其初等变化等.约定:1) 希尔密码常使用Z26字母表, 在此贴中, 我们也以Z26最为字母表进行讲解.在附带源码中有两种字母表选择.2) 大家都知道最小的质数是2, 1 既不是质数也不是合数. 在此我们定义1对任何质数的模逆为其本身.因为对于任意质数n, 有: 1*1 % n = 1 的. 也应该是很好理解的.相关概念:线性代数中的逆矩阵: 在线性代数中, 大家都知道,对于一个n阶矩阵M , 如果存在一个n阶矩阵N ,使得M * N = E (其中:E为n阶单位矩阵), 则称矩阵N 为矩阵M 的逆矩阵, 并记为M^-1.比如2阶矩阵M = [3,6] , 则很容易得知其逆矩阵:[2,7]M^-1 = [7/9, -2/3][-2/9, 1/3] .关于这个逆矩阵是如何计算出的, 通常的有两种方法:一是使用伴随矩阵, 通过计算行列式得到. 所用公式为: M^-1 = M^* / D . (其中M^*为M 的伴随矩阵, D为M的行列式的值)二是通过增广矩阵, 在M右侧附加一个n阶单位矩阵, 再通过初等变换将增广矩阵的左侧变换为一个n阶单位矩阵, 这时右侧便是所求的逆矩阵.希尔密码原理:加密者在对明文加密前会选择一个加密秘匙, 这个秘匙最终会以一个m矩阵的形式参与到加密算法中的. 在加密者选定了加密秘匙后, m便得到了确定,这时,加密者将明文按m个字母一组的形式分成多组, 最后一组不足m个字母的按特定的方式补齐. 这样就形成了很多组由m个字母组成的单个向量, 然后对每一个m阶向量, 我们用它去乘以确定好了的秘匙.如下为其中的一个分组A向量加密后变为B向量的过程:[A1,A2,A3 ... Am] * M = [B1,B2,B3 ... Bm] .我们将所有相乘后的向量连在一起, 便得到了密文. 这便是希尔密码的加密.加密是非常简单的, 我们接下来来看一下解密部分, 解密部分要比加密部分稍微复杂一点点.上面我们提到了矩阵的逆矩阵. 大家可能会想, 既然明文A向量乘以秘匙M矩阵就得到了密文B向量, 那么我们将B向量乘以M的逆矩阵, 不就可以得到A了吗?大家的想法不错, 但是请注意:我们上面的那个例子矩阵[3,6]的逆矩阵为[7/9, -2/3] , 发现了吧, 我们如果硬是去按常规方法计算M的逆矩阵的话, 你得到的[2,7] [-2/9, 1/3]很可能是一个含有分式的矩阵. 这显然是不符合要求的.(为什么? )__asm{cmp you, "想知道为什么"jnz @F]有的人会说,就算有分式又怎么样? 虽然分式在计算机中以浮点数体现, 但我还是让B乘以这个浮点数表示的M^1, 然后对结果进行四舍五入, 不久OK了? 不错这样是可以达到效果. 但是! 有以下几个缺点:1): 平白无辜的扯到了浮点运算, 还要进行四舍五入, 降低了算法效率使其看起来相当愚蠢.2): 解密秘匙体现的局限性, 其实是这个意思: 假如现在为二战时期, 我们需要派一位特工在盟军的两个司令部之间传达密钥. 而且规定密钥只能以A~Z这26个字母的形式体现. 也即你的秘匙只能是字母构成的, 接受方得到秘匙后按照Z26表对应将A当作0,B当作1,... Z当作25 来翻译, 然后解密. 这种情况下, 上面的分式就不好表示了. 当然在真实情况下, 密钥是怎么个传输法, 那还要区别对待.于是, 我们想对于一个矩阵能否有另外一种的逆使得其各元素皆为Z26范围中的元素同时可以顺利地完成解密了? 当然有.方法一: 最小公倍数法这种方法是在前面的矩阵逆的基础上来做文章的. 如下.我们接着上面那个带分式的M^-1来说, 大家观察一下, 很容易知道, 其中的分母9 其实为原矩阵M的行列式值: 9 = 3*7 - 2*6;那我们将M^-1乘以9, 不就可以消掉分母了吗? 呵呵. 不行的.我们要想消掉分母, 肯定得乘以一个数, 那到底要乘以多少了. 这里因为我们是Z26的字母表. 我们要保证乘以一个数之后, 原来的明文字母所增大的部分一定得是26的整数倍. 也即如下第一步:设a为明文中的一个字母. x 为需要对当前的M^-1乘以的倍数. t为任意整数.ax = a + 26t. 恒成立. ==>> t = a(x-1)/26 .要想t为整数, 则x = 26p+1 .p >=1. 这里我们一般取p =1 即可. 因此x = 27.(及字母表个数加一)第二步:要消掉分母, 我们必须乘以分母D(M)的倍数. 其中D(M)为M的行列式值.得结果:所求x = 最小公倍数( 27, D(M) ) .具体到上例中, x = 最小公倍数(27,9) = 27.我们将上面的M^-1 乘以27 得到: [21, -18][-6, 9 ]到了这一步, 我们得到了含负数的希尔逆矩阵.(注意: 从这里开始我们区别对待两种逆矩阵).而负数还是不能用Z26中的字母表示, 怎么办? 没关系, 对于负数我们加上26即可. 因为我们加上的是26,所以对于最终的取模是没有影响的. 因此我们得到:希尔逆矩阵M^-1 = [21,8][20,9]方法二:纯整数初等变化法(这个名字和上面那个最小公倍数法都是我自己想出来的名字, 可能不好听. 呵呵.)这一种方法的思想就是元素的模逆. 因为我们这里是Z26, 我们不关心元素的实际大小, 只关心它对26取模后的数值.因此, 在对原矩阵M求逆时, 我们先将M变为增广矩阵A, 再对A的每一列进行循环, 在第j列中, 从第j行开始, 每个元素遍历, 依次检查是否对26存在模逆. 否的话, 检查下一个, 是的话,乘以其模逆, 于是该元素结果得1, 再得到其行数为i ,将此行与第j行互换(目的就是为了形成对角线的n个1), 然后对余下的行, 用此行乘以余下行的第j个元素的值去依次减余下的行,这样就使得当前第j列的n-1个0得以生成. 如果某列一直检查下去都没有元素存在模逆的话, 则该矩阵M不存在希尔逆矩阵.文字有时还是不如代码好说话, 看代码吧:(这次的希尔密码辅助软件,我使用的是C#.我嫌用C弄一些框框太麻烦,所以选择了简单的C#,弄一些框框是为了看中间过程.同时, 也能布置大家一个作业: 即读懂附件中的C#代码, 用C或C++重写之. 呵呵, 我想未装.NET Framework的非Vista朋友如果为了使用附件中的bin的话, 还是得自己用其他语言重写一边的吧//检查元素a是否对n存在模逆代码:public bool CheckReverse(int a){int n = (int)zt;int p = 2;while(p*p<n){if (a%p == n%p && 0 == a%p){return false;}p++;}//when a equals with 1 , it's also reversiablereturn true;}//得到元素a对n的模逆代码:public int GetReverse(int a){int n = (int)zt;int q, p, t;int x = 0, y = 1, z;q = n;p = a;z = (int)q / p;while (1 != p && 1 != q) {t = p;p = q % p;q = t;t = y;y = x - y * z;x = t;z = (int)q / p;}y = y % n;if (y < 0){y += n;}//when a equals with 1 , it return 1. return y;}//使用纯整数初等变换法计算M的希尔逆矩阵.代码:public bool Calc_M_1(){int[,] A = new int[nRank, nRank * 2]; int[] T = new int[nRank*2];int i,j,k;//construct the [M|E] matrix Afor (i = 0; i < nRank;++i){for (j = 0; j < nRank * 2;++j){if (j<nRank){A[i, j] = nMatrix[i, j]; }else{if (nRank == j-i){A[i, j] = 1;}else{A[i, j] = 0;}}}}//begin to metamorphose Aint a_1 = 0;for (j = 0; j < nRank;++j){//step1: get one reversiable element for (i = j; i < nRank /*+ 1*/; ++i){if (CheckReverse(A[i,j])){a_1 = GetReverse(A[i, j]);for (k = 0; k < nRank * 2;++k) {A[i, k] *= a_1;A[i, k] %= (int)zt;T[k] = A[i, k];A[i, k] = A[j, k];A[j, k] = T[k];}goto step2;}if (nRank - 1 == i) //last element of the column, still no one is reversiable{return false;}}step2: //create the n-1 zeros of the columnfor (i = 0; i < nRank ; ++i){if (i != j){int t = A[i, j]; //first element of Row i .for (k = 0; k < nRank * 2; k++){A[i, k] -= t * A[j, k];A[i, k] %= (int)zt;if (A[i, k]<0){A[i, k] += (int)zt;}}}}}//construct M_1for (i = 0; i < nRank;++i){for (j = 0; j < nRank;++j){nDeMatrix[i,j] = A[i,j+nRank];}}return true;}效果图:我们来截几张图看看:n阶希尔逆矩阵的计算:加密测试:(注意明文中的3个O分别变为了O,S,A . 很好地隐藏了字频信息.)。
Hill密码是一种简单的加密手段。
优点是:可以实现同一个字母在不同的上下文中,对应密文中不同的字母。
缺点是:加密前明文是几个字母,加密后还是几个字母。
容易被穷举。
以下,我们都用英文字母举例,比较简单明了下面简要介绍一下加密过程首先,要将26个字母,编号,例如a:1b:2c:3d:4e:5f:6g:7h:8i:9j:10k:11l:12m:13n:14o:15p:16q:17r:18s:19t:20u:21v:22w:23x:24y:25z:0其次,确定密钥,在这里其实就是加密矩阵,Hill2密码对应的是一个二阶矩阵,Hill n密码对应的就是一个N接矩阵了,我们这里取二阶,比较简单。
如:取个加密矩阵A=(1 2;0 3) 说明:大家凑合着看啊,其实是 1 2是一行,0 3是一行。
画个矩阵太麻烦了以下说明,矩阵里加了分号就表示换行哈有了字母编号表和密钥就万事具备了。
我们来将下面一段字母加密woshigetiancai首先,将字母两两分组wo ,sh, ig, et, ia, nc, ai。
这里刚好是偶数个字母,如果是奇数个,就重复一次,最后一个字母,凑成偶数。
其次,查询字母标号表,将分好组的字母,写成向量形式,其实就是写成一个1*2的矩阵(我就讨厌,那些书,明明就是个1*2矩阵,偏偏要要定义成向量,增加无谓的概念):如w 对应23,o对应15,写成向量(23;15)(这个是竖着写的,实在不好意思,矩阵实在不太好画,手头没matlab)以此类推,得到7组向量,分别是wo对应的(23;15) sh对应的(19;8) ig对应的(9;7) et对应的(5;20) ia对应的(9;1)nc 对应的(14;3) ai对应的(1;9)将这些向量分别左乘密钥注意:这里矩阵这个东西比较麻烦,不符合乘法交换律,两个矩阵左乘和右乘的结果是不一样的左乘就是将密钥放到左边,右边是向量A*P(向量)又得到7组向量,分别是(38;45),(27;24),(16;24),(25;60),(10;3),(17;9),(10;27)这时候,我们就遇到了一个问题,我们定义的字母标号表是0~25的,这里又是45 ,又是60的,怎么办??没关系,遇到比25大的,我们就减26 知道,让数字落在0~25之间就可以了例如原向量(38;45)我们就变成了(12;19),这样就落在我们的字母标号表里了,很简单吧以此类推,最后得到的7组向量就变成了(12;19),(1;24),(14;24),(25;8),(10;3),(17;9),(10,1)最后再将数字通过字母标号表对照过来就可以了这里是lsaxnxyhjcqija 这样就和原字符有很大的区别了吧。
Hill密码本⽂为转载他⼈⽂章这⾥主要介绍的是:古典密码之 hill密码加密解密过程的编程实现。
⾸先,请看对我对hill密码做的简单介绍。
hill密码是古典密码中多表代换密码部分的重要⼀环,以下的介绍节选⾃百度,想要深⼊了解的请查阅书籍补充相关知识。
原理:希尔密码(Hill Password)是运⽤基本矩阵论原理的替换密码,由Lester S. Hill在1929年发明。
每个字母当作26数字:A=0, B=1, C=2...⼀串字母当成n维向量,跟⼀个n×n的矩阵相乘,再将得出的结果模26。
注意⽤作加密的矩阵(即密匙)在\mathbb_^n必须是可逆的,否则就不可能译码。
只有矩阵的和26,才是可逆的。
需要的知识储备:1)线性代数基础知识.2) 基础知识.约定:1)希尔密码常使⽤Z26字母表,在此贴中,我们也以Z26最为字母表进⾏讲解.在附带源码中有两种字母表选择.2) ⼤家都知道最⼩的质数是2,1 既不是质数也不是合数. 在此我们定义1对任何质数的模逆为其本⾝.因为对于任意质数n,有: 1*1 % n = 1 的. 也应该是很好理解的.过程:1)加密:密⽂=明⽂*密钥矩阵(注:明⽂要被分割成与密钥维数相同的⼀维⾏列式)2)解密:明⽂=密⽂*密钥矩阵的逆(注:要求与加密过程相同)加密解密过程如下图:例:加密过程:解密:对上述过程进⾏编程,主要的函数声明如下:12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25/*** 头⽂件名称:hillcrypto.h* 实现⽂件名称:hillcrypto.cpp* 项⽬名称:多表代换密码之hill密码* 作者:邹明* 完成时间:2016.3.14**/#ifndef __HILLCRTPTO_H__#define __HILLCRTPTO_H__#include<iostream>using namespace std;#include<assert.h>#include <iomanip>#define ROW 4 //密钥⾏数为4#define COV 4 //密钥列数为4void InputKeys(float keys[ROW][COV]); //输⼊密钥void InputWords(char*words); //输⼊明⽂void InputObwords(char*words); //输⼊密⽂void PopKeys(float keys[ROW][COV]); //输出密钥void Encryption(float keys[ROW][COV], char*words, char*crypto); //明⽂加密2526 27 28 29 30 31 32 33void Encryption(float keys[ROW][COV], char*words, char*crypto); //明⽂加密void Decode(float keys[ROW][COV], char*words, char*crypto); //密⽂解密bool Gauss(float A[ROW][COV], float B[ROW][COV], int n); //⾼斯消去法求逆矩阵void ObMatrix(float a[ROW][COV], float b[ROW][COV], int n); //求密钥逆矩阵void menu(); //菜单#endif函数实现过程中的主函数实现以及菜单函数实现如下:12345 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56/* 实现⽂件名称:hillcrypto.cpp */#include"hillcrypto.h"int main(){menu(); //菜单+选择system("pause");return0;}void menu(){float keys[ROW][COV] = { 8, 6, 9, 5, 6, 9, 5, 10, 5, 8, 4, 9, 10, 6, 11, 4 }; //加密矩阵(默认密钥) float obkeys[ROW][COV] = { 0 }; //解密矩阵(密钥逆矩阵)char words[100] = { 0 };char crypto[100] = { 0 };char obwords[100] = { 0 };bool flag = true; //菜单选择bool chose = false; //密钥选择char cn = 0;while(flag){int n = 0;cout << endl;cout << "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<< endl;cout << "\t\t\t1.输⼊密钥"<< endl;cout << "\t\t\t2.明⽂加密"<< endl;cout << "\t\t\t3.密⽂解密"<< endl;cout << "\t\t\t4.退出"<< endl << endl;cout << "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<< endl;cout << "请选择->:";cin >> n;switch(n){case1:system("cls");cout << "默认密钥为:";PopKeys(keys);cout << "请问您要重新输⼊密钥? y/n"<< endl << "请选择->:";cin >> cn;if((cn == 'y') || (cn == 'Y')){InputKeys(keys); //输⼊密钥}else if((cn == 'n') || (cn == 'N')){cout << "感谢您选择使⽤默认密钥!"<< endl;}elsecout << "输⼊有误,请重新选择!"<< endl;system("pause");break;case2:system("cls");InputWords(words); //输⼊明⽂Encryption(keys, words, crypto); //加密cout << "密⽂是->:"<< crypto << endl;56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 cout << "密⽂是->:"<< crypto << endl;system("pause");break;case3:system("cls");InputObwords(crypto); //输⼊密⽂ObMatrix(keys, obkeys, COV); //计算解密矩阵 Decode(obkeys, obwords, crypto); //解密cout << "明⽂是->:"<< obwords << endl;system("pause");break;case4:system("cls");cout << endl << endl << endl;cout << setw(15) << "谢谢使⽤!"<< endl;flag = false;system("pause");break;default:cout << "选择有误,请重新选择!"<< endl;system("pause");break;}}}输⼊明⽂函数和输⼊密⽂函数:123456 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40void InputWords(char*words) //输⼊明⽂{assert(words);cout << "请输⼊明⽂:";char*start = words;int flag = 1;getchar();while(flag){*words = getchar();words++;if(*(words - 1) == '\n'){*words = '\0';flag = 0;}}words = start;while(*start){if(('A'<= *start) && (*start <= 'Z')){*words = *start;words++;}else if(('a'<= *start) && (*start <= 'z')) {*words = *start - 32;words++;}start++;}*words = '\0';cout << "输⼊成功!"<< endl;}void InputObwords(char*words) //输⼊密⽂{assert(words);cout << "请输⼊密⽂:";char*start = words;40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 char*start = words;int flag = 1;getchar();while(flag){*words = getchar();words++;if(*(words - 1) == '\n'){*words = '\0';flag = 0;}}words = start;while(*start){if(('A'<= *start) && (*start <= 'Z')){*words = *start;words++;}else if(('a'<= *start) && (*start <= 'z')) {*words = *start - 32;words++;}start++;}*words = '\0';cout << "输⼊成功!"<< endl;}输⼊密钥与输出密钥函数:12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26void InputKeys(float keys[ROW][COV]) //输⼊密钥{cout << "请输⼊密钥:"<< endl;for(size_t i = 0; i < ROW; i++){cout << "请输⼊第"<< i << "⾏密钥("<<ROW<<"个数):"; for(size_t j = 0; j < COV; j++){cin >> keys[i][j];}}cout << "输⼊成功 !"<< endl;}void PopKeys(float keys[ROW][COV]) //输出密钥{cout << "密钥为:"<< endl;for(size_t i = 0; i < ROW; i++){for(size_t j = 0; j < COV; j++){cout << keys[i][j] << " ";}cout << endl;}}加密函数:123 4 5void Encryption(float keys[ROW][COV], char*words, char*crypto) //加密函数{assert(words);int len = strlen(words);5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int len = strlen(words);char*start = words;while(len > 0){int matrix[ROW] = { 0 };for(int i = 0; i < ROW; i++){if(*start)matrix[i] = *start - 'A';elsematrix[i] = 0;start++;}len -= ROW;int cry[ROW] = { 0 };for(int i = 0; i < ROW; i++){int temp = 0;for(int j = 0; j < COV; j++){temp = matrix[j] * keys[j][i] + temp; }cry[i] = temp % 26;*crypto = 'A'+ cry[i]; //计算密⽂crypto++;}}}解密函数,以及求逆矩阵函数:1234567891011 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39void Decode(float obkeys[ROW][COV], char*words, char*crypto)//解密函数{assert(crypto);int len = strlen(crypto);char*start = crypto;while(len > 0){int matrix[ROW] = { 0 };for(int i = 0; i < ROW; i++){if(*start)matrix[i] = *start - 'A';elsematrix[i] = 0;start++;}len -= ROW;int cry[ROW] = { 0 };for(int i = 0; i < ROW; i++){int temp = 0;for(int j = 0; j < COV; j++){temp = matrix[j] * obkeys[j][i] + temp;}cry[i] = temp % 26;*words = 'A'+ cry[i]; //计算明⽂words++;}}}39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107void ObMatrix( float a[ROW][COV], float b[ROW][COV], int n) //求逆矩阵函数{int i, j; //定义矩阵的⾏列式if(Gauss(a, b, n)){cout << "该⽅阵的逆矩阵为: \n";for(i = 0; i < n; i++){cout << setw(4);for(j = 0; j < n; j++){int temp =b[i][j]/ 1;float num = b[i][j] - temp;if(fabs(num) < 0.50)b[i][j] = (int)temp;elseb[i][j] = temp + (int)(num * 2);cout << b[i][j] << setw(10);}cout << endl;}}cout << "逆矩阵(mod26):"<< endl;for(int i = 0; i < ROW; i++){cout << setw(4);for(int j = 0; j < COV; j++){if(b[i][j] >= 0){b[i][j] = (int)b[i][j] % 26;}else{b[i][j] = 26 + (int)b[i][j] % 26;}cout << b[i][j] << setw(6);}cout << endl;}}bool Gauss(float A[ROW][COV], float B[ROW][COV], int n) //⾼斯消去法{int i, j, k;float max, temp;float t[ROW][COV]; //临时矩阵//将A矩阵存放在临时矩阵t[n][n]中for(i = 0; i < n; i++){for(j = 0; j < n; j++){t[i][j] = A[i][j];}}//初始化B矩阵为单位阵for(i = 0; i < n; i++){for(j = 0; j < n; j++){B[i][j] = (i == j) ? (int)1 : 0;}}for(i = 0; i < n; i++){//寻找主元max = t[i][i];k = i;for(j = i + 1; j < n; j++){if(fabs(t[j][i]) > fabs(max)){max = t[j][i];k = j;}}107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 }//如果主元所在⾏不是第i⾏,进⾏⾏交换if(k != i){for(j = 0; j < n; j++){temp = t[i][j];t[i][j] = t[k][j];t[k][j] = temp;//B伴随交换temp = B[i][j];B[i][j] = B[k][j];B[k][j] = temp;}}//判断主元是否为0, 若是, 则矩阵A不是满秩矩阵,不存在逆矩阵 if(t[i][i] == 0){cout << "There is no inverse matrix!";return false;}//消去A的第i列除去i⾏以外的各⾏元素temp = t[i][i];for(j = 0; j < n; j++){t[i][j] = t[i][j] / temp; //主对⾓线上的元素变为1B[i][j] = B[i][j] / temp; //伴随计算}for(j = 0; j < n; j++) //第0⾏->第n⾏{if(j != i) //不是第i⾏{temp = t[j][i];for(k = 0; k < n; k++) //第j⾏元素 - i⾏元素*j列i⾏元素 {t[j][k] = t[j][k] - t[i][k] * temp;B[j][k] = B[j][k] - B[i][k] * temp;}}}}return true;}程序运⾏结果:选择:1选择:y选择:n选择 2.明⽂加密:选择 3.密⽂解密:选择 4.退出:。