首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PolarSSL AES-CBC加密字符串后,我无法解密该字符串

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

Stack Overflow用户
提问于 2012-12-12 15:08:54
回答 3查看 2.8K关注 0票数 3

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

这是我的代码

代码语言:javascript
复制
#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算法的理解不是很清楚,因为我的英文很差,读一些文章太难了。

-添加

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

代码语言:javascript
复制
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;
}

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

代码语言:javascript
复制
Before encrypt:ABCDEFGHIJKLMN
After decrypt:ABCDEFGHYC
                        LMN

如何获取IV

EN

回答 3

Stack Overflow用户

发布于 2012-12-12 16:54:07

编辑:正如Daniel在他的答案中指出的,一个大问题是你试图使用一个随机的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或谷歌KeyCzar

总而言之,您的特定问题可以通过使用256位密钥来解决,但是在这个抽象级别上实现您自己的密码系统时,您应该三思而后行。

票数 4
EN

Stack Overflow用户

发布于 2012-12-12 17:20:26

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

代码语言:javascript
复制
havege_random(&hs, IV, 16);

在加密和解密之间。

还要确保使用一个32字节的字符数组作为aes_setkey_encaes_setkey_dec的第二个参数,因为您读取的内容已经超出了字符串的末尾。根据编译器的不同,可能会导致使用不同的密钥进行加密和解密(因此,会失败)。

(编辑问题的后半部分)

更改此设置:

代码语言:javascript
复制
strncpy(IV, IV2, 16);           //copy IV

要这样做:

代码语言:javascript
复制
memcpy(IV2, IV, 16);           //copy IV

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

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

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

票数 4
EN

Stack Overflow用户

发布于 2015-03-16 20:04:18

我刚把64改成了14

代码语言:javascript
复制
aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);

每件事都运行得很好!

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13834602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档