我写了一个用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算法的理解不是很清楚,因为我的英文很差,读一些文章太难了。
-添加
我听从了你的建议,更改了我的代码,现在我使用相同的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
发布于 2012-12-12 16:54:07
编辑:正如Daniel在他的答案中指出的,一个大问题是你试图使用一个随机的IV来解密(这不会给你你期望的结果)。但是,我建议您也阅读本答案的其余部分。
首先,aes_set_key_enc和aes_set_key_dec不接受密码作为输入,它们接受密钥。密钥应该是一个与密钥长度一样长的完全随机值(在本例中是一个32字节的随机字符串,因为您希望使用256位密钥)。
在本例中,您使用短密码调用aes_set_key_enc/aes_set_key_dec,但告诉它应该使用256位密钥,这将导致这些函数使用密码之外的内存作为密钥的一部分,并将导致加密和解密密钥不同。
总而言之,AES (或任何密码算法)需要随机密钥,算法本身没有将密码扩展为密钥的概念。
如果您想使用密码作为密钥,则需要一些函数将非随机密码扩展为伪随机密钥。要做到这一点,唯一明智的方法是使用一个设计为加密安全但也很慢的函数,这是为了减少对密码的暴力攻击的风险。
很好用的函数是Colin Percivals scrypt,bcrypt或PBKDF2,其中我推荐最多的是scrypt。
但是,我想强调的是,您可能根本不应该在这个抽象级别上工作。您正在使用的原语(块密码、CBC模式)处于非常低的抽象级别,使用这些原语构建密码系统可能非常危险。例如,您不对密文使用任何类型的身份验证,这可能会使您的实现容易受到选择的密文攻击。
我认为,如果你想在你的应用程序中使用密码学,最好的方法是尝试在更高的抽象级别上工作,例如使用Dan Bernsteins优秀的NaCl或谷歌KeyCzar。
总而言之,您的特定问题可以通过使用256位密钥来解决,但是在这个抽象级别上实现您自己的密码系统时,您应该三思而后行。
发布于 2012-12-12 17:20:26
你正在使用一个随机的IV来解密。这是错误的。您需要使用与加密相同的IV进行解密。只需删除第二个调用
havege_random(&hs, IV, 16);在加密和解密之间。
还要确保使用一个32字节的字符数组作为aes_setkey_enc和aes_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添加到密文或将其存储在文件头中,具体取决于方案。
话虽如此,我同意这样的建议:除非你知道自己在做什么,否则不要使用加密原语构建自己的加密协议。
发布于 2015-03-16 20:04:18
我刚把64改成了14
aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);每件事都运行得很好!
https://stackoverflow.com/questions/13834602
复制相似问题