C中的Vigenere密码
Vigenere's cipher in C
我用 C 编写了一个程序,该程序接受纯文本和密码并使用 vigenere 密码生成密文。虽然代码在大多数情况下都能产生正确的输出,但我发现了一个产生意外输出的示例,而我自己却找不到问题所在。输出是这样的:
jess@laptop:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn
LXF OPV EFR NHR [0002]
末尾的框没有按应有的方式显示,它的意思是表示 bash 试图显示 ascii 字符 2,但复制和粘贴无法正确显示。这是来自维基百科的密码示例文本,它是我发现的唯一破坏我的程序的文本(我不知道原因是什么,所以我无法复制它)但我确信还有更多字符串这将产生类似的结果。我怀疑我做了一些会产生未定义行为的事情,但我不确定。我在这里做错了什么?
我的代码:
// vigenere.c - Takes a plaintext and a cipher key from argv[1] and argv[2] and produces the cipher text according to Vigenere's cipher
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void string_clean(char *source) //Courtesy (mostly) of user 'Aaron' of Whosebug
{
char *i = source;
char *j = source;
while(*j != 0) {
*i = *j++;
if( *i != ' ' && (isupper(*i) || islower(*i)) )
i++;
}
*i = 0;
}
char *vigenere_enc(char plain[], char cipher[])
{
char *cipher_text;
string_clean(plain);
string_clean(cipher);
int plain_len = strlen(plain);
int cipher_len = strlen(cipher);
if( !(cipher_text = calloc(plain_len, sizeof(char))) )
return 0;
for(int i = 0; i < cipher_len; i++) {
if(isupper(cipher[i]))
cipher[i] -= 'A';
else if(islower(cipher[i]))
cipher[i] -= 'a';
}
int j = 0;
for(int i = 0; i < plain_len; i++, j++) {
if(j == cipher_len)
j = 0;
if(isupper(plain[i]))
plain[i] -= 'A';
else if(islower(plain[i]))
plain[i] -= 'a';
cipher_text[i] = ((plain[i] + cipher[j]) % 26) + 'A';
}
return cipher_text;
}
int main(int argc, char *argv[])
{
if(argc != 3)
return 1;
char *cipher = vigenere_enc(argv[2], argv[1]);
for(int i = 0; i < strlen(cipher); i++) {
if(i % 3 == 0 && i != 0)
putchar(' ');
putchar(cipher[i]);
}
putchar('\n');
return 0;
}
非常感谢所有 help/suggestions!
您需要 NUL-terminate 您的输出字符串。 :-( 这也意味着您对 calloc
的调用(不过您实际上应该只使用 malloc
)应该指定 plain_len + 1
,而不仅仅是 plain_len
。
我用 C 编写了一个程序,该程序接受纯文本和密码并使用 vigenere 密码生成密文。虽然代码在大多数情况下都能产生正确的输出,但我发现了一个产生意外输出的示例,而我自己却找不到问题所在。输出是这样的:
jess@laptop:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn
LXF OPV EFR NHR [0002]
末尾的框没有按应有的方式显示,它的意思是表示 bash 试图显示 ascii 字符 2,但复制和粘贴无法正确显示。这是来自维基百科的密码示例文本,它是我发现的唯一破坏我的程序的文本(我不知道原因是什么,所以我无法复制它)但我确信还有更多字符串这将产生类似的结果。我怀疑我做了一些会产生未定义行为的事情,但我不确定。我在这里做错了什么? 我的代码:
// vigenere.c - Takes a plaintext and a cipher key from argv[1] and argv[2] and produces the cipher text according to Vigenere's cipher
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void string_clean(char *source) //Courtesy (mostly) of user 'Aaron' of Whosebug
{
char *i = source;
char *j = source;
while(*j != 0) {
*i = *j++;
if( *i != ' ' && (isupper(*i) || islower(*i)) )
i++;
}
*i = 0;
}
char *vigenere_enc(char plain[], char cipher[])
{
char *cipher_text;
string_clean(plain);
string_clean(cipher);
int plain_len = strlen(plain);
int cipher_len = strlen(cipher);
if( !(cipher_text = calloc(plain_len, sizeof(char))) )
return 0;
for(int i = 0; i < cipher_len; i++) {
if(isupper(cipher[i]))
cipher[i] -= 'A';
else if(islower(cipher[i]))
cipher[i] -= 'a';
}
int j = 0;
for(int i = 0; i < plain_len; i++, j++) {
if(j == cipher_len)
j = 0;
if(isupper(plain[i]))
plain[i] -= 'A';
else if(islower(plain[i]))
plain[i] -= 'a';
cipher_text[i] = ((plain[i] + cipher[j]) % 26) + 'A';
}
return cipher_text;
}
int main(int argc, char *argv[])
{
if(argc != 3)
return 1;
char *cipher = vigenere_enc(argv[2], argv[1]);
for(int i = 0; i < strlen(cipher); i++) {
if(i % 3 == 0 && i != 0)
putchar(' ');
putchar(cipher[i]);
}
putchar('\n');
return 0;
}
非常感谢所有 help/suggestions!
您需要 NUL-terminate 您的输出字符串。 :-( 这也意味着您对 calloc
的调用(不过您实际上应该只使用 malloc
)应该指定 plain_len + 1
,而不仅仅是 plain_len
。