仍然发现在C中使用内存很难。我正在阅读一个文本文件,其中我将包含名称和40个字符的随机字符串的每行文本存储到2个缓冲区中,char buffer1 [128和char buffer2 [128]使用人们似乎不喜欢的fscanf(),后来我需要把JUST字符串(在缓冲区的其余部分没有任何填充或空格)并使用AES-CBC-128加密它然后在解密它。我在名称上使用md5生成一个16字节的密钥,我在加密过程中使用它,随机初始化向量再次为16字节。现在,加密/解密几乎可以正常工作,如果我自己输入40个字符串到AES加密函数中(即字符串后来正确解密,但事先出现了一些额外的乱码字符),但如果我通过包含字符串的缓冲区进入函数,解密出来所有带有乱码的字符(换句话说它不起作用)。如果我尝试使缓冲区足够小以完全包含字符串(char buffer [40]),则加密/解密不起作用。如果我尝试为C中的字符串中的终结符设置char buffer [41],我会收到Core Dump错误。 我仍然是一个C菜鸟,无法弄清楚我做错了什么! 注:如果我使用48个字节作为加密长度(AES BLOCK SIZE的16个字节的倍数),则它不起作用。当我使用40个字节作为加密长度(与要加密的数据相同)时,它几乎像我上面说的那样工作。请解释我如何能够正确地使用AES_CBC_Encrypt和所有!我使用的是openssl,测试代码是:
void alice() {
FILE *fp=fopen("alice.txt","r"); //read mode
int j;
char buffer1[128], buffer2[128]; //buffer1->names, buffer2->data
unsigned char h_j[SHA_DIGEST_LENGTH];
unsigned char k_j[MD5_DIGEST_LENGTH];
//loops over the 25 lines in alice.txt file
for (j=0; j<n_alice; j++) {
//read a_j data_j into addresses of buffer1 and buffer2
fscanf(fp,"%s %s\n",(char*)&buffer1, (char*)&buffer2); //buffer1=names, buffer2=data
if (dbg) printf("Reading %s %40s\n", buffer1, buffer2);
//Calculate h_j=SHA1(a_j)
SHA1((unsigned char*)&buffer1, strlen(buffer1),(unsigned char*)h_j);
//Calculate k_j=MD5(a_j)
MD5((unsigned char*)&buffer1, strlen(buffer1), (unsigned char*)k_j);
//Encrypt c_j=AES-CBC-ENC(k_j,data_j)
//using MD5 digest as the key for the AES CBC
//initialization vector
unsigned char init_vector[AES_BLOCK_SIZE];
RAND_bytes(init_vector, AES_BLOCK_SIZE); //16 bytes
const size_t encslength = 48;//((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[40];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(k_j, sizeof(k_j), &enc_key);
AES_cbc_encrypt(buffer2, enc_out, strlen(buffer2), &enc_key, init_vector, AES_ENCRYPT);
AES_set_decrypt_key(k_j, sizeof(k_j), &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, init_vector, AES_DECRYPT);
printf("original:\t %s\n", buffer2);
printf("encrypt:\t %s\n", enc_out);
printf("decrypt:\t %s\n", dec_out);
}
fclose(fp);
}
Alice.txt包含:
yves E9D0EEFC4C6DD81F2A7BDE99CCE833FB7B2BDD6D 亚当D6C33F73EC7175AEA67DEC98427B42AAF6E5E04C 大卫F58EEB1DDB9511A3F220A4B10F01F88260BC99AB umbert F6A6127E6562C5816433FB3B7C341C45A8805DCB 维多利亚CCF10AA4A4725C964FFF78BA3694393ADE1D7B6C nick C8030118EB5E037F6131D9BB5B1BEF0A3F2AC458 小峰E9B45ECAE2F42D59B90EACB2CA8E75A969A7EFAB 前夕D8DA8BC812D9CD72B91EB7AF49D099A9BE85AB43 所属分类:CC039D2746A3C55E4BA1DCEE46F329E4CA7E0A1A 佛罗伦萨C2DFD6650343659BFB530FE719139AB4D3F2BEDC 赫伯特CDCB4196E8CA9002219EC7A8F372911501BD1BBD 常春藤E53BC8DF9A81BDD881E5352BCE11A2BF0F33236B 插孔C5213B5F8DC334010586FB094A63D50A7572470E osvald D0FBD9B2102DF6C41C8B26F25AF3E18ACF2BD27C 史蒂文C9A3AB53FAA9E8243A63EBDC3257D1C8CCEC7D1C 凯文D7C6774E65DBB8F312F50183C87D67BC6FBF7BED 加文F4C1945162294DD902C6BC11EE23BF8B682AC6C9 卢克DF2FD780E13F9511411EC92B476D167A6D9F334A 马丁FE6D5175D3B6E49B6649DBD6F21559F15847CA31 pippo DA908468DBE291E4DDEB082E36E9F5BB316A3C3C 理查德EC26FF6B364C51DCA5A7CB5D711BCC85946D2517 特洛伊F1165BE81E08B38A42C582A8F25C2CC382233F3D zach EF19BED4FD6732C92437A3F65C4BE69A5010994D 威廉EC74AA8C93AA32EFF85EC4437F50F1F86AECAC29 查理C86D2F8A3EF1F03127628C7CF9C6D9FB730DACBF我只是从main调用alice()来测试它。
答案 0 :(得分:0)
我设法弄清楚了我的严重错误。这一行:
AES_set_encrypt_key(k_j, sizeof(k_j), &enc_key);
应该是:
AES_set_encrypt_key(k_j, sizeof(k_j)*8, &enc_key);
enclength
函数中的declength
和AES_CBC_Encrypt()
显然也应该相同。所以我使用48字节进行加密和解密,否则它对我不起作用。我可能错了,但是当我使用strlen(buffer2)
进行加密(40字节)时,解密只能正确解密部分字符串,其余部分仍然是乱码字符。 - val37
答案 1 :(得分:-1)
我自己也在努力解决OpenSSL的错误记录API。功能本身在Assembler中实现真的无济于事,所以即使是源代码也无济于事。但我能够发现你犯过的一些错误:
AES_set_encrypt_key
将位大小作为第二个参数,而不是字节。init_vector
必须相同。因为2.你的整个例子不适用于sha1。 MD5_DIGEST_LENGTH
并且只有巧合才有16个字节(128位)。初始化向量也会被加密操作更改,因此您可以一次又一次地向块链添加其他数据。但是,由于你没有遵循3.并且使用更改后的矢量进行解密而不首先重置它,这就是你的解密返回“乱码”的原因。
作为一个例子,我拿走了你的代码,抛弃了不必要的东西,并提取了加密/解密操作来清理重要的部分:
void encrypt(unsigned char* buf, size_t length, const AES_KEY* const enc_key, const unsigned char* iv)
{
unsigned char local_vector[AES_BLOCK_SIZE];
memcpy(local_vector, iv, AES_BLOCK_SIZE);
AES_cbc_encrypt(buf, buf, length, enc_key, local_vector, AES_ENCRYPT);
}
我正在努力阅读和写作。如您所见,init_vector在本地复制以保持原始值不变。我做了类似的解密。
void decrypt(unsigned char* buf, size_t length, const AES_KEY* const dec_key, const unsigned char* iv)
{
unsigned char local_vector[AES_BLOCK_SIZE];
memcpy(local_vector, iv, AES_BLOCK_SIZE);
AES_cbc_encrypt(buf, buf, length, dec_key, local_vector, AES_DECRYPT);
}
这就是我对你的代码所做的。我没有改变fscanf,因为我们应该专注于问题而不是让人困惑:
void tst_function()
{
FILE *fp=fopen("alice.txt","r"); //read mode
char buffer1[128], buffer2[128]; //buffer1->names, buffer2->data
memset(buffer1, 0, sizeof(buffer1));
memset(buffer2, 0, sizeof(buffer2));
// remember, this won't work with any other size
unsigned char k_j[AES_BLOCK_SIZE];
//until end of file
while(fscanf(fp,"%s %s\n",(char*)&buffer1, (char*)&buffer2) > 0)
{
printf("Reading %s %40s\n", buffer1, buffer2);
printf("original:\t%s\n", buffer2);
unsigned char init_vector[AES_BLOCK_SIZE];
RAND_bytes(init_vector, AES_BLOCK_SIZE);
// PKCS 5 Padding
// ((inputs_length + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
const size_t encslength = 48;
unsigned char enc_out[encslength];
memset(enc_out, 0, sizeof(enc_out));
strncpy(enc_out, buffer2, sizeof(enc_out));
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(k_j, sizeof(k_j)*8, &enc_key);
AES_set_decrypt_key(k_j, sizeof(k_j)*8, &dec_key);
encrypt(enc_out, encslength, &enc_key, init_vector); //see above
printf("encrypted:\t%s\n", (char*)enc_out);
decrypt(enc_out, encslength, &dec_key, init_vector); //see above
printf("decrpyted:\t%s\n", (char*)enc_out);
}
fclose(fp);
}
它现在做了人们期望它做的事情。您必须非常小心密钥大小。因为我不知道的悬空零(来自琴弦)我撞了很多。此外,您可以查看EVP Symmetric Encryption and Decryption和XTS,查看最多512位的密钥。