【问题标题】:Invalid characters generated while encrypting with openssl evp aes_256_ctr() mode使用 openssl evp aes_256_ctr() 模式加密时生成的无效字符
【发布时间】:2015-02-16 21:44:29
【问题描述】:

我的想法是在客户端服务器模型中进行文件加密,我使用 openssl evp 进行加密。我需要将密文存储在文本文件中并将其发送给客户端。但我无法做到这一点,因为我发现密文中存在无法存储在文件中的无效字符。

这是我的加密代码:

EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_aes_256_ctr(), NULL, NULL, NULL,
        do_encrypt);
OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx) == 32);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx) == 16);

EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);

//receive the file contents in chunks of 1024 bytes
while ((inlen = recv(connfd, inbuf, sizeof inbuf, 0)) > 0) {
    fprintf(stdout,"\nReceived %d bytes",inlen);
    fflush(stdout);
    fprintf(stdout,"\nOriginal: %s",inbuf);
    fflush(stdout);
    //use encrypt_update() to encrypt the chunks
    if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)) {
        /* Error */
        EVP_CIPHER_CTX_cleanup(&ctx);
        return 0;
    }
    //write the encrypted text to out file
    fprintf(stdout,"\nEncrypted: %s %d",outbuf, inlen);
    fflush(stdout);
    fwrite(outbuf, sizeof(char), outlen, fp);
    //clear the buffer
    memset(inbuf,0, strlen(inbuf));
    memset(outbuf,0, strlen(outbuf));
}
//use encrypt_final() to encrypt the final letf out block of chunk is any
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) {
    /* Error */
    EVP_CIPHER_CTX_cleanup(&ctx);
    return 0;
}
//write the encrypted text to out file
fwrite(outbuf, sizeof(char), outlen, fp);
EVP_CIPHER_CTX_cleanup(&ctx); //cleanup
fclose(fp); //close the file

我参考了这个链接,其中报告并解决了带有解密的无效字符问题。

Issues with encrypting a file using openssl evp api(aes256cbc)

希望有人能帮帮我。

提前致谢。

【问题讨论】:

  • 是什么让您认为加密发出的字节是可打印的字符
  • 我打印它们只是为了检查是否正在生成某些东西....我不认为它们是可打印的....但我也不能存储和传输它们?
  • 您的错误检查看起来正确。假设 PKCS5 填充等效,请检查您的输出文件以确保它是块大小(16 字节)的倍数。如果你想要一些可显示的东西,你可以在将输出字节发送到输出文件之前对输出字节进行 base64 或简单的十六进制编码。当然,您还必须在执行解密时将其反转以取回原始加密字节。
  • 是的,我会检查输出文件,是的,我尝试了 base64,但它似乎不适合我......我在解密时丢失了一些数据......
  • 虽然不一定是您描述的问题的原因,但您在每个循环结束时所做的 memsets 看起来很可疑 - 您正在使用 strlen 来确定要设置的字节数为 0,但这些不是以 null 结尾的字符串,因此无法保证 strlen 将返回正确的值,因此您可能会将不相关的内存清零。在适当的情况下,这很容易导致意外行为或崩溃。

标签: c encryption openssl evp-cipher


【解决方案1】:

使用 openssl evp aes_256_ctr() 模式加密时生成的无效字符...

...因为我发现密文中存在无法存储在文件中的无效字符

我认为这是你的问题。不完全正确。

您可以在文件中存储任何内容(任何字符)。 C 字符串有点不同,但你不是在使用字符串。

所有字符在密文中的概率均等(与任何其他字符的概率相同,例如 0x00、0x01、...'A'、'B'、...'a'、'b'、... , 0xFE, 0xFF)。


fprintf(stdout,"\n原件:%s",inbuf);

如果inbuf 嵌入了NULL,这可能是个问题。我以为你在处理文件而不是字符串?


memset(inbuf,0, strlen(inbuf));
memset(outbuf,0, strlen(outbuf));

正如 Iridium 所说,这些不是必需的。您应该使用像recv 这样的函数的返回值(而不是依赖于像NULL 这样的特殊字符,因为它同样可能在密文中(同样可能与任何其他字符一样,如0x00、0x01、...'A ', 'B', ... 'a', 'b', ..., 0xFE, 0xFF)。


EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_aes_256_ctr(), NULL, NULL, NULL, do_encrypt);
...

您也忽略了返回值。这通常是个坏主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2021-08-05
    • 2019-11-19
    • 2021-06-06
    • 1970-01-01
    • 2012-05-09
    • 2017-05-29
    相关资源
    最近更新 更多