我用c编写了这个程序,使用hill密码,但加密和解密输出总是错误的



我有一个使用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密码的实现中有大量的逻辑错误。具体来说,主要问题是:

  1. C不允许零大小的数组。二维数组是数组的数组。plaintxtencrypted都有[2][0],它只是一个零大小数组的二维数组。最低需要[2][1](或[2][2]是好的),
  2. 如果在命令行中给出了"-d",则永远不会初始化encrypted
  3. 在你计算矩阵乘法的结果之前,你必须填满plaintxtencrypted。计算每个加密/明文字符需要两个原始字符分别在plaintxtencrypted中,
  4. 您的矩阵乘法与字符向量是错误的。矢量图中i的位置应该是j,例如k = k + matrix[i][j] * plaintxt[j][0];k = k + inverse_matrix[i][j] * encrypted[j][0];
  5. 您的matrixinverse值必须是mod(26)以及由输入的2个字符输入形成的矢量。您似乎想要使用小写字符,因此保持一致并将输入转换为小写并减去'a'以获得所需的基于零的向量
  6. 你必须通过检查返回来验证每个用户输入您使用的任何输入函数。

下面的代码注释中还有一些额外的小问题,但是把所有的东西放在一起并使用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

看一遍,有问题就告诉我。

最新更新