在c中创建一长串加密的子串

时间:2012-10-12 10:55:47

标签: c encryption mcrypt string-length

我正在尝试创建一个由加密子字符串生成的长字符串。对于我正在使用AES128libmcrypt的加密。代码工作正常,但我得到一个较短的输出然后我应该和一声哔哔声。我想这是因为我正在使用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;
}

4 个答案:

答案 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);

别担心,编译器不会对其进行优化。它实际上不够聪明,无法判断你是否会再次使用该区域。