C语言中的Vigenere Square解密
Vigenere Square Decryption in C
我正在尝试使用密码和存储在数组中的 vigenere 方块来加密和解密消息。我能够成功加密消息,但是我无法弄清楚之后如何再次解密它。有任何想法吗?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void encrypt(char *text, char *pass, int n, int m, char *vs);
void decrypt(char *text, char *pass, int n, int m, char *vs);
void vigsq(char *vs);
main()
{
char text[] = "HELLOWORLD";
char pass[] = "MAGIC";
int n, m;
char vs[26*26];
char *vsPointer, *textPointer, *passPointer;
char command;
char inputfile[10];
char outputfile[10];
//printf("Please enter e/d, pass phrase, input file, output file:");
//scanf("%c, %s, %s, %s", &command, &pass, &inputfile, &outputfile);
vsPointer = vs;
textPointer = text;
passPointer = pass;
vigsq(vsPointer);
//printf("%c, %s, %s, %s\n", command, pass, inputfile, outputfile);
n = strlen(text);
m = strlen(pass);
//printf("%d, %d", n, m);
encrypt(textPointer, passPointer, n, m, vsPointer);
printf("%s\n", text);
decrypt(textPointer, passPointer, n, m, vsPointer);
printf("%s\n", text);
}
void encrypt(char *text, char *pass, int n, int m, char *vs)
{
int i;
int ascii1;
int ascii2;
int passcount = 0;
char encrypt;
for (i = 0; i < n; i++)
{
ascii1 = (int)text[i];
ascii2 = (int)pass[passcount];
ascii1 = ascii1 - 64;
ascii2 = ascii2 - 64;
encrypt = vs[((ascii1 -1)*26) + (ascii2)];
// printf("%d, %d, %c\n", ascii1, ascii2, encrypt);
text[i] = encrypt;
passcount++;
if (passcount == m)
{
passcount = 0;
}
}
}
void decrypt(char *text, char *pass, int n, int m, char *vs)
{
int i;
int ascii1;
int ascii2;
int passcount = 0;
char decrypt;
for (i = 0; i < n; i++)
{
ascii1 = (int)text[i];
ascii2 = (int)pass[passcount];
ascii1 = ascii1 - 64;
ascii2 = ascii2 - 64;
decrypt = vs[//Don't know what to put here];
//printf("%d, %d, %c\n", ascii1, ascii2, decrypt);
text[i] = decrypt;
passcount++;
if (passcount == m)
{
passcount = 0;
}
}
}
void vigsq(char *vs)
{
char alphabet[] = {'A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int a = 0, i, j, count = 0;
for(i = 1; i <= 26*26; i++)
{
vs[i] = alphabet[a];
a++;
if (i % 26 == 0)
{
count++;
a = count;
}
if (a == 26)
{
a = 0;
}
}
}
(请忽略我稍后会实现的 I/O 内容。)
感谢您的帮助:)
当你对一个字母进行编码时,你在密码字母 m[j]
的行和 Vigenère table 中的明文字母 p[i]
的列中查找字母。解码时,必须在密码字母所在的行中找到加密字母c[i]
所在的列。在代码中,加密是一个简单的 table 查找,但解密不是。
不过您并不真的需要 table。您可以在算法上描述 Vigenère 密码。该密码实际上只是一个凯撒密码——一个简单的字母移位 &ndash,其中移位量由密码中的当前字母决定。加密就是向前移动,解密就是向后移动:
c[i] = (p[i] + m[j]) % 26
p[i] = (c[i] - m[j]) & 26
在此公式中,字母由数字 0 (A) 到 25 (Z) 表示。请记住,索引在 C 中从零开始。这也意味着您必须从字母中减去 'A'
(65),而不是 64。
因为解密和加密非常相似,您可以在带有操作模式标志的单个函数中实现它们:
enum {
Encrypt,
Decrypt
};
void vigenere(char *text, const char *pass, int mode)
{
int i;
int passcount = 0;
for (i = 0; text[i] != '[=11=]'; i++)
{
int ascii1 = text[i] - 'A';
int ascii2 = pass[passcount] - 'A';
// Negate shift for decryption
if (mode == Decrypt) ascii2 = -ascii2;
text[i] = 'A' + (26 + ascii1 + ascii2) % 26;
passcount++;
if (pass[passcount] == '[=11=]') passcount = 0;
}
}
注意事项:
- 公式中加26是为了防止取负数的余数,在C中得到负数
- 只有当所有字符都是大写字母时,该代码才有效。
- 省略了明确的字符串长度;您可以通过检查当前字符是终止空字符
'[=17=]'
. 来测试是否已到达 C 字符串的末尾
像这样调用这段代码:
int main()
{
char text[] = "HELLOWORLD";
const char *pass = "MAGIC";
printf("plain %s\n", text);
vigenere(text, pass, Encrypt);
printf("crypt %s\n", text);
vigenere(text, pass, Decrypt);
printf("decpt %s\n", text);
return 0;
}
我正在尝试使用密码和存储在数组中的 vigenere 方块来加密和解密消息。我能够成功加密消息,但是我无法弄清楚之后如何再次解密它。有任何想法吗?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void encrypt(char *text, char *pass, int n, int m, char *vs);
void decrypt(char *text, char *pass, int n, int m, char *vs);
void vigsq(char *vs);
main()
{
char text[] = "HELLOWORLD";
char pass[] = "MAGIC";
int n, m;
char vs[26*26];
char *vsPointer, *textPointer, *passPointer;
char command;
char inputfile[10];
char outputfile[10];
//printf("Please enter e/d, pass phrase, input file, output file:");
//scanf("%c, %s, %s, %s", &command, &pass, &inputfile, &outputfile);
vsPointer = vs;
textPointer = text;
passPointer = pass;
vigsq(vsPointer);
//printf("%c, %s, %s, %s\n", command, pass, inputfile, outputfile);
n = strlen(text);
m = strlen(pass);
//printf("%d, %d", n, m);
encrypt(textPointer, passPointer, n, m, vsPointer);
printf("%s\n", text);
decrypt(textPointer, passPointer, n, m, vsPointer);
printf("%s\n", text);
}
void encrypt(char *text, char *pass, int n, int m, char *vs)
{
int i;
int ascii1;
int ascii2;
int passcount = 0;
char encrypt;
for (i = 0; i < n; i++)
{
ascii1 = (int)text[i];
ascii2 = (int)pass[passcount];
ascii1 = ascii1 - 64;
ascii2 = ascii2 - 64;
encrypt = vs[((ascii1 -1)*26) + (ascii2)];
// printf("%d, %d, %c\n", ascii1, ascii2, encrypt);
text[i] = encrypt;
passcount++;
if (passcount == m)
{
passcount = 0;
}
}
}
void decrypt(char *text, char *pass, int n, int m, char *vs)
{
int i;
int ascii1;
int ascii2;
int passcount = 0;
char decrypt;
for (i = 0; i < n; i++)
{
ascii1 = (int)text[i];
ascii2 = (int)pass[passcount];
ascii1 = ascii1 - 64;
ascii2 = ascii2 - 64;
decrypt = vs[//Don't know what to put here];
//printf("%d, %d, %c\n", ascii1, ascii2, decrypt);
text[i] = decrypt;
passcount++;
if (passcount == m)
{
passcount = 0;
}
}
}
void vigsq(char *vs)
{
char alphabet[] = {'A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int a = 0, i, j, count = 0;
for(i = 1; i <= 26*26; i++)
{
vs[i] = alphabet[a];
a++;
if (i % 26 == 0)
{
count++;
a = count;
}
if (a == 26)
{
a = 0;
}
}
}
(请忽略我稍后会实现的 I/O 内容。) 感谢您的帮助:)
当你对一个字母进行编码时,你在密码字母 m[j]
的行和 Vigenère table 中的明文字母 p[i]
的列中查找字母。解码时,必须在密码字母所在的行中找到加密字母c[i]
所在的列。在代码中,加密是一个简单的 table 查找,但解密不是。
不过您并不真的需要 table。您可以在算法上描述 Vigenère 密码。该密码实际上只是一个凯撒密码——一个简单的字母移位 &ndash,其中移位量由密码中的当前字母决定。加密就是向前移动,解密就是向后移动:
c[i] = (p[i] + m[j]) % 26
p[i] = (c[i] - m[j]) & 26
在此公式中,字母由数字 0 (A) 到 25 (Z) 表示。请记住,索引在 C 中从零开始。这也意味着您必须从字母中减去 'A'
(65),而不是 64。
因为解密和加密非常相似,您可以在带有操作模式标志的单个函数中实现它们:
enum {
Encrypt,
Decrypt
};
void vigenere(char *text, const char *pass, int mode)
{
int i;
int passcount = 0;
for (i = 0; text[i] != '[=11=]'; i++)
{
int ascii1 = text[i] - 'A';
int ascii2 = pass[passcount] - 'A';
// Negate shift for decryption
if (mode == Decrypt) ascii2 = -ascii2;
text[i] = 'A' + (26 + ascii1 + ascii2) % 26;
passcount++;
if (pass[passcount] == '[=11=]') passcount = 0;
}
}
注意事项:
- 公式中加26是为了防止取负数的余数,在C中得到负数
- 只有当所有字符都是大写字母时,该代码才有效。
- 省略了明确的字符串长度;您可以通过检查当前字符是终止空字符
'[=17=]'
. 来测试是否已到达 C 字符串的末尾
像这样调用这段代码:
int main()
{
char text[] = "HELLOWORLD";
const char *pass = "MAGIC";
printf("plain %s\n", text);
vigenere(text, pass, Encrypt);
printf("crypt %s\n", text);
vigenere(text, pass, Decrypt);
printf("decpt %s\n", text);
return 0;
}