3

我写了一个程序来加密一个字符串PolarSSL AES-CBC

这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <polarssl/aes.h>
#include <polarssl/havege.h>

int main()
{
    char buff[2][64] = {"Who can tell me WHY?", ""};
    havege_state hs;
    int retval;
    unsigned char IV[16];

    aes_context enc_ctx;
    aes_context dec_ctx;

    aes_setkey_enc(&enc_ctx, "password", 256);
    aes_setkey_dec(&dec_ctx, "password", 256);

    havege_init(&hs);
    havege_random(&hs, IV, 16);

    //encrypt
    aes_crypt_cbc(&enc_ctx, AES_ENCRYPT, 64, IV, buff[0], buff[1]);
    havege_random(&hs, IV, 16);

    //decrypt
    aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV, buff[1],buff[0]);

    printf("After decrypt:%s\n", buff[0]);
    return 0;
}

但是当我运行它时,我在解密后得到了错误的文本。

我对AES算法不太了解,因为我的英语很差,看一些文章太难了。

----------------------------------添加者 midCat---------------------- ----------------------

我听从了您的建议,现在更改我的代码我使用相同的 IV 和 256 位密钥,这是新代码

int main()
{
    char buff[2][64] = {"ABCDEFGHIJKLMN", ""};
    havege_state hs;
    int retval;
    unsigned char IV[16];
    unsigned char IV2[16];
    unsigned char key[32];

    aes_context enc_ctx;
    aes_context dec_ctx;

    havege_init(&hs);
    havege_random(&hs, IV, 16);
    havege_random(&hs, key, 32);
    strncpy(IV, IV2, 16);           //copy IV

    aes_setkey_enc(&enc_ctx, key, 256);
    aes_setkey_dec(&dec_ctx, key, 256);


    //encrypt
    aes_crypt_cbc(&enc_ctx, AES_ENCRYPT, 64, IV, buff[0], buff[1]);
    printf("Before encrypt:%s\n", buff[0]);

    //decrypt
    aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);
    printf("After decrypt:%s\n", buff[0]);
    return 0;
}

我编译它,并运行了很多次,得到了相同的输出:

Before encrypt:ABCDEFGHIJKLMN
After decrypt:ABCDEFGHYC
                        LMN

如何获得IV

4

3 回答 3

4

编辑:正如丹尼尔在他的回答中指出的那样,一个大问题是您正在尝试使用随机 IV 进行解密(这不会给您预期的结果)。但是,我建议您也阅读此答案的其余部分。

首先,aes_set_key_enc不要aes_set_key_dec将密码作为输入,它们采用密钥。密钥应该是与密钥长度一样长的完全随机值(在您的情况下为 32 字节的随机字符串,因为您想使用 256 位密钥)。

在您的情况下,您使用aes_set_key_enc/aes_set_key_dec短密码进行调用,但告诉它应该使用 256 位密钥,这将导致这些函数使用密码之外的内存作为密钥的一部分,并导致加密和解密密钥不同。

回顾一下,AES(或任何密码算法)需要随机密钥,算法本身没有将密码扩展为密钥的概念。

如果要将密码用作密钥,则需要一些将非随机密码扩展为伪随机密钥的功能。唯一明智的方法是使用设计为加密安全但速度较慢的功能,这是为了减轻对密码进行暴力攻击的风险。

使用好的函数是 Colin Percivals scryptbcryptPBKDF2,我最推荐 scrypt 。

但是,我想强调的是,您可能根本不应该在这个抽象级别上工作。您使用的原语(分组密码、CBC 模式)处于非常低的抽象级别,使用这些原语构建密码系统可能非常危险。例如,您没有在密文上使用任何类型的身份验证,这可能会使您的实现面临选择的密文攻击。

我认为,如果您想在应用程序中使用密码学,最好的方法是尝试在更高的抽象级别上工作,例如使用 Dan Bernsteins 出色的NaCl或 Googles KeyCzar

回顾一下,您的特定问题可以通过使用 256 位密钥来解决,但您应该三思而后行在此抽象级别实现自己的密码系统。

于 2012-12-12T08:54:06.727 回答
4

您正在使用随机 IV 进行解密。那是错的。您需要与用于加密的相同 IV 进行解密。只需删除第二个调用

havege_random(&hs, IV, 16);

在加密和解密之间。

还要确保使用 32 字节的 char 数组作为第二个参数aes_setkey_encaes_setkey_dec因为您正在读取字符串的末尾,就像现在一样。根据编译器的不同,它可能会导致用于加密和解密的密钥不同(因此失败)。

(编辑问题的后半部分)

改变这个:

strncpy(IV, IV2, 16);           //copy IV

对此:

memcpy(IV2, IV, 16);           //copy IV

memcpystrncpy因为 IV 是可以包含字符串 terminator 的随机数据'\0',并且这两个函数的第一个参数是目标,而不是源。您将字符串从 IV2 复制到 IV,而不是将内存从 IV 复制到 IV2。

并回答有关如何获取 IV 进行解密的问题:通常,IV 只是与密文一起发送。每个 IV 只能使用一次,并且不能预测,但不必保密。一种常见的结构是为每条消息选择一个随机 IV,然后简单地将 IV 附加到密文或将其存储在文件头中,具体取决于场景。

话虽如此,我同意不要使用加密原语构建自己的加密协议的建议,除非你知道自己在做什么。

于 2012-12-12T09:20:25.963 回答
-1

我刚把 64 改成 14

aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);

一切都很好!

于 2015-03-16T12:04:18.477 回答