用PolarSSL AES-CBC加密字符串后,我无法解密字符串

时间:2012-12-12 07:08:54

标签: c encryption cryptography aes polarssl

我编写了一个用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

3 个答案:

答案 0 :(得分:4)

编辑:丹尼尔在他的回答中指出,一个大问题是你试图使用一个随机的IV来解密(这不会给你你期望的结果)。但是,我建议你也阅读其余的答案。

首先,aes_set_key_encaes_set_key_dec不接受密码作为输入,它们接受密钥。一个密钥应该是一个完全随机的值,只要密钥长度(在你的情况下是一个32字节的随机字符串,因为你想使用256位密钥)。

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

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

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

使用的好功能是Colin Percivals scryptbcryptPBKDF2 我建议最多的是scrypt。

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

我认为,如果您想在应用程序中使用加密技术,最好的方法是尝试在更高的抽象级别上工作,例如使用Dan Bernsteins优秀的NaCl或Google KeyCzar。< / p>

总结一下,您可以使用256位密钥解决您的具体问题,但是您应该在这个抽象级别上考虑实现自己的密码系统。

答案 1 :(得分: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

那是memcpy而不是strncpy,因为IV是随机数据,可以包含字符串终止符'\0',这两个函数的第一个参数是目标,而不是源。您将一个字符串从IV2复制到IV而不是从IV复制到IV2。

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

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

答案 2 :(得分:-1)

我刚刚在

中将64改为14
aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);

并且每件事情都很好!