我正在尝试创建一个由加密子字符串生成的长字符串。对于我正在使用AES128
和libmcrypt
的加密。代码工作正常,但我得到一个较短的输出然后我应该和一声哔哔声。我想这是因为我正在使用strlen
,但我不知道,我怎么能避免这种情况。我将非常感谢一些建议。这是我的代码:
char *Encrypt( char *key, char *message){
static char *Res;
MCRYPT mfd;
char *IV;
int i, blocks, key_size = 16, block_size = 16;
blocks = (int) (strlen(message) / block_size) + 1;
Res = calloc(1, (blocks * block_size));
mfd = mcrypt_module_open(MCRYPT_RIJNDAEL_128, NULL, "ecb", NULL);
mcrypt_generic_init(mfd, key, key_size, IV);
strncpy(Res, message, strlen(message));
mcrypt_generic(mfd, Res, block_size);
//printf("the encrypted %s\n", Res);
mcrypt_generic_deinit(mfd);
mcrypt_module_close(mfd);
return (Res);
}
char *mkline ( int cols) {
int j;
char seed[] = "thesecretmessage", key1[]="dontusethisinput", key2[]="abadinputforthis";
char *encrypted, *encrypted2, *in = malloc(cols * 16);
encrypted = Encrypt(key1, seed);
sprintf(in, "%s", encrypted);
encrypted2= Encrypt(key2, encrypted);
printf("encrypted2 before for-loop %s\n", encrypted2);
printf("encrypted2 before for loop len %d\n", strlen(encrypted2));
for (j=1; j<cols; j++) {
strcat(in, encrypted2);
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
printf("encrypted2 %s on position %d\n" , encrypted2,j);
printf("encrypted2 len %d\n", strlen(encrypted2));
}
free(encrypted);
free(encrypted2);
return in;
}
int main(int argc, char *argv[]) {
char *line = mkline(15);
printf("line %s\n", line);
printf("line lenght %d\n", strlen(line));
return 0;
}
答案 0 :(得分:1)
您尝试打印的加密字符串包含一个字节流,其中单个字节的值范围为0到255.由于您使用的是加密安全算法,因此值的分布非常接近均匀。
由于您尝试通过控制台打印加密字符串,因此控制台会将某些字节解释为控制字符(请参阅Bell character),这些控制字符不可打印但会产生其他效果,例如播放哔声。
此外,strlen
没有做你认为它应该做的事情,因为加密的字符串不是以空值终止的,而是在其他字节中包含零,并且与NULL终止字符串不同,它们没有特殊含义。您需要将字符串的长度存储在其他位置。
答案 1 :(得分:1)
因为您正在打印控制字符,所以会发出哔声。
同样strlen
返回大小,直到第一个'\ 0'字符(因为字符串零终止)。这就是为什么你得到的长度比预期的少,因为加密的消息可能包含零。
您可以执行以下操作来返回结果长度:
char *Encrypt(const char *key, const char *message, int *result_len)
{
*result_len = blocks * block_size;
}
另外
memmove(encrypted2, Encrypt(key2, encrypted2),strlen(seed));
这一行应该会产生内存泄漏,因为每次调用Encrypt
时都要调用calloc
(分配新内存),完成后需要释放。
你可能应该使用memcpy,如果有机会目的地且源可能重叠,则主要使用memmove。
答案 2 :(得分:0)
很简单,您将二进制输出(任何字节值)直接视为可打印文本。代码点低于32(十六进制20)的任何字符都不是。例如。 BELL的ASCII值(查找)可能对您有意义。用十六进制打印生成的字节,你应该没问题。
答案 3 :(得分:0)
我想补充一点,一般情况下,如果可以,在加密后清除任何保存明文/未加密邮件的内存是一种好习惯。这不是很好的编码实践,而是良好的密码学实践。
这可以通过以下方式完成: memset(buffer,0,length_of_buffer);
别担心,编译器不会对其进行优化。它实际上不够聪明,无法判断你是否会再次使用该区域。