我编写了一个用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
?
答案 0 :(得分:4)
首先,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或Google KeyCzar。< / p>
总结一下,您可以使用256位密钥解决您的具体问题,但是您应该在这个抽象级别上考虑实现自己的密码系统。
答案 1 :(得分:4)
您正在使用随机IV进行解密。那是错的。您需要与用于加密的相同的IV进行解密。只需删除第二次调用
即可havege_random(&hs, IV, 16);
在加密和解密之间。
还要确保使用32字节的char数组作为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添加到密文或将其存储在文件头中,具体取决于场景。
话虽如此,我同意不使用加密原语构建自己的加密协议的建议,除非你知道你在做什么。
答案 2 :(得分:-1)
我刚刚在
中将64改为14aes_crypt_cbc(&dec_ctx, AES_DECRYPT, 64, IV2, buff[1],buff[0]);
并且每件事情都很好!