我有一个使用Hill密码编写程序的任务。该程序需要加密和解密,但不能同时运行。要运行加密,用户必须输入"。/希尔-e"在命令行和"/希尔-d"解密。程序必须提示并从用户那里读取一个2X2矩阵的整数键。它还必须通过检查行列式来验证键是否有效。这个矩阵的逆也必须计算出来。然后提示用户为明文输入2个字符,然后将其更改为整数。在此之后,程序将提示加密或解密。
编译时没有错误。创建矩阵,检查行列式,计算逆,并将字符更改为正确的整数,所有这些都完全按照预期工作。我的问题是我没有得到加密或解密的正确输出。我尝试了几种不同的变化,但都不起作用。有人愿意指出错误吗?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int main(int argc, char * argv[]){
int i,j,k;
int matrix[2][2],adjoint[2][2],plaintxt[2][0],encrypted[2][0],decrypted[2][0];
long determinant;
float inverse_matrix[2][2];
char msg[10];
printf("nEnter your elements for a 2X2 matrix key.Each integer should be separated by a space.n");
for(i = 0; i < 2; i++)
{
for(j = 0; j < 2; j++)
{
scanf("%d", &matrix[i][j]);
}
}
printf("nThe 2X2 Key Matrix:n");
for(i = 0; i < 2; i++)
{
for(j = 0; j < 2; j++)
{
printf("%dt", matrix[i][j]);
}
printf("n");
}
determinant = matrix[0][0]*matrix[1][1] - matrix[1][0]*matrix[0][1];
if(determinant == 0)
{
printf("nInvalid key. The matrix does not have an inverse.n");
printf("n");
exit(EXIT_FAILURE);
}
adjoint[0][0] = matrix[1][1];
adjoint[1][1] = matrix[0][0];
adjoint[0][1] = -matrix[0][1];
adjoint[1][0] = -matrix[1][0];
printf("nInverse of the 2X2 Key Matrix:n");
for(i = 0; i < 2; i++)
{
for(j = 0; j < 2; j++)
{
inverse_matrix[i][j] = (adjoint[i][j])/(float)determinant;
printf("%lft", inverse_matrix[i][j]);
}
printf("n");
}
printf("n Enter 2 plaintext characters to cipher.n");
scanf("%s", msg);
for(i = 0; i < 2; i++)
{
plaintxt[i][0] = msg[i] - 97;
printf("%d", plaintxt[i][0]);
}
if(argc >= 2)
{
if(strcmp(argv[1], "-e") == 0)
{
for(i = 0; i < 2; i++){
k = 0;
for(j = 0; j < 2; j++){
k = k + matrix[i][j] * plaintxt[i][0];
}
encrypted[i][0] = k % 26;
}
printf("nEncrypted cipher text: ");
for(i = 0; i < 2; i++)
printf("%c", encrypted[i][0] + 97);
}
else if(strcmp(argv[1], "-d") == 0)
{
for(i = 0; i < 2; i++){
k = 0;
for(j = 0; j < 2; j++){
k = k + inverse_matrix[i][j] * encrypted[i][0];
}
plaintxt[i][0] = k % 26;
}
printf("nDecrypted cipher text: ");
for(i = 0; i < 2; i++)
printf("%c", plaintxt[i][0] + 97);
}
}
return 0;}
继续我的评论,在Hill密码的实现中有大量的逻辑错误。具体来说,主要问题是:
- C不允许零大小的数组。二维数组是数组的数组。
plaintxt
和encrypted
都有[2][0]
,它只是一个零大小数组的二维数组。最低需要[2][1]
(或[2][2]
是好的), - 如果在命令行中给出了
"-d"
,则永远不会初始化encrypted
, - 在你计算矩阵乘法的结果之前,你必须填满
plaintxt
和encrypted
。计算每个加密/明文字符需要两个原始字符分别在plaintxt
或encrypted
中, - 您的矩阵乘法与字符向量是错误的。矢量图中
i
的位置应该是j
,例如k = k + matrix[i][j] * plaintxt[j][0];
和k = k + inverse_matrix[i][j] * encrypted[j][0];
, - 您的
matrix
和inverse
值必须是mod(26)
以及由输入的2个字符输入形成的矢量。您似乎想要使用小写字符,因此保持一致并将输入转换为小写并减去'a'
以获得所需的基于零的向量 - 你必须通过检查返回来验证每个用户输入您使用的任何输入函数。
下面的代码注释中还有一些额外的小问题,但是把所有的东西放在一起并使用fgets()
来读取字符串输入(在清空scanf()
留下的'n'
中的stdin
之后),您可以做如下的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
/* quick helper-function to empty stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != 'n' && c != EOF) {
c = getchar();
}
}
int main (int argc, char * argv[]){
int i,j,k;
int matrix[2][2],
adjoint[2][2],
plaintxt[2][2] = {{0},{0}}, /* initialize your text arrays */
encrypted[2][2] = {{0},{0}};
long determinant;
float inverse_matrix[2][2];
char msg[1024]; /* don't SKIMP on buffer size */
/* avoid long strings, split them, puts() is fine for no converisons */
puts ("nEnter your elements for a 2X2 matrix key."
"Each integer should be separated by a space.");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
/* validate EVERY input */
if (scanf ("%d", &matrix[i][j]) != 1) {
fputs ("invalid integer input.n", stderr);
return 1;
}
matrix[i][j] %= 26; /* matrix must be % 26 */
}
}
empty_stdin(); /* get rid of chars + 'n' remaining in stdin */
puts ("nThe 2X2 Key Matrix:");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
printf("%dt", matrix[i][j]);
}
putchar ('n'); /* you putchar() a single-character */
}
determinant = matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1];
if (determinant == 0)
{
/* error output goes to stderr */
fputs ("nInvalid key. The matrix does not have an inverse.n",
stderr);
exit (EXIT_FAILURE);
}
adjoint[0][0] = matrix[1][1];
adjoint[1][1] = matrix[0][0];
adjoint[0][1] = -matrix[0][1];
adjoint[1][0] = -matrix[1][0];
puts ("nInverse of the 2X2 Key Matrix:");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
/* inverse matrix must be % 26 as well */
inverse_matrix[i][j] = fmodf ((adjoint[i][j])/(float)determinant,
26.);
printf ("%lft", inverse_matrix[i][j]);
}
putchar ('n');
}
if (argc >= 2)
{
if (strcmp(argv[1], "-e") == 0)
{
/* move prompt and read into proper block */
fputs ("nenter 2 plaintext chars to encipher: ", stdout);
/* should read/validate all user input with fgets */
if (!fgets (msg, sizeof msg, stdin)) {
puts ("(user canceled input)");
return 0;
}
/* simply assign plaintxt before loop, zero-based for cipher */
plaintxt[0][0] = tolower(msg[0]) - 'a';
plaintxt[1][0] = tolower(msg[1]) - 'a';
/* ensure you don't read beyond end of msg */
for (i = 0; msg[i] && i < 2; i++){
k = 0;
for(j = 0; j < 2; j++){
k = k + matrix[i][j] * plaintxt[j][0];
}
encrypted[i][0] = k % 26;
}
/* should exit if i != 2 here */
printf("nEncrypted cipher text: ");
for (i = 0; i < 2; i++)
putchar (encrypted[i][0] + 'a');
putchar ('n');
}
else if (strcmp(argv[1], "-d") == 0)
{
/* move prompt and read into proper block */
fputs ("nenter 2 enciphered chars to decipher: ", stdout);
/* should read/validate all user input with fgets */
if (!fgets (msg, sizeof msg, stdin)) {
puts ("(user canceled input)");
return 0;
}
/* simply assign encrypted before loop, zero-based for cipher */
encrypted[0][0] = tolower(msg[0]) - 'a';
encrypted[1][0] = tolower(msg[1]) - 'a';
/* ensure you don't read beyond end of msg */
for (i = 0; msg[i] && i < 2; i++){
k = 0;
for(j = 0; j < 2; j++){
k = k + inverse_matrix[i][j] * encrypted[j][0];
}
plaintxt[i][0] = k % 26;
}
/* should exit if i != 2 here */
printf("nDecrypted cipher text: ");
for(i = 0; i < 2; i++)
putchar (plaintxt[i][0] + 'a');
putchar ('n');
}
}
return 0;
}
(注意:这些是使您的代码工作的最小更改,而不是代码的最佳重写—这是留给您的)
使用/输出示例
使用简单的测试用例,其中矩阵由1 2 3 4
和"ab"
的字符串输入组成,代码按需要进行加密和解码,例如
$ ./bin/hillcipher -e
Enter your elements for a 2X2 matrix key.Each integer should be separated by a space.
1 2 3 4
The 2X2 Key Matrix:
1 2
3 4
Inverse of the 2X2 Key Matrix:
-2.000000 1.000000
1.500000 -0.500000
enter 2 plaintext chars to encipher: ab
Encrypted cipher text: ce
和解密:
$ ./bin/hillcipher -d
Enter your elements for a 2X2 matrix key.Each integer should be separated by a space.
1 2 3 4
The 2X2 Key Matrix:
1 2
3 4
Inverse of the 2X2 Key Matrix:
-2.000000 1.000000
1.500000 -0.500000
enter 2 enciphered chars to decipher: ce
Decrypted cipher text: ab
看一遍,有问题就告诉我。