【发布时间】:2015-02-17 22:49:55
【问题描述】:
仍然发现很难在 C 中使用内存。我正在读取一个文本文件,其中我将包含名称和 40 个字符的随机字符串的每一行文本存储到 2 个缓冲区中,char buffer1[128] 和char buffer2[128] 使用人们似乎不喜欢的 fscanf() ,后来我需要只取字符串(在缓冲区的其余部分没有任何填充或空白)并使用 AES-CBC-128 加密它然后稍后在解密它。我在名称上使用 md5 来生成一个 16 字节的密钥,我在加密过程中使用它,并再次生成一个 16 字节的随机初始化向量。现在,加密/解密几乎可以正常工作,如果我自己在 AES 加密函数中键入 40 个字符的字符串(即字符串稍后被正确解密,但事先出现了一些额外的乱码),但如果我传递包含字符串进入函数,解密出来的都是乱码(换句话说,它不起作用)。如果我尝试使缓冲区足够小以准确包含字符串(字符缓冲区 [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 包含:
伊夫 E9D0EEFC4C6DD81F2A7BDE99CCE833FB7B2BDD6D 亚当 D6C33F73EC7175AEA67DEC98427B42AAF6E5E04C 大卫 F58EEB1DDB9511A3F220A4B10F01F88260BC99AB F6A6127E6562C5816433FB3B7C341C45A8805DCB 维多利亚 CCF10AA4A4725C964FFF78BA3694393ADE1D7B6C 尼克 C8030118EB5E037F6131D9BB5B1BEF0A3F2AC458 晓峰E9B45ECAE2F42D59B90EACB2CA8E75A969A7EFAB 夏娃 D8DA8BC812D9CD72B91EB7AF49D099A9BE85AB43 鲍勃 CC039D2746A3C55E4BA1DCEE46F329E4CA7E0A1A 佛罗伦萨 C2DFD6650343659BFB530FE719139AB4D3F2BEDC 赫伯特CDCB4196E8CA9002219EC7A8F372911501BD1BBD 常春藤 E53BC8DF9A81BDD881E5352BCE11A2BF0F33236B 千斤顶 C5213B5F8DC334010586FB094A63D50A7572470E 奥斯瓦尔德 D0FBD9B2102DF6C41C8B26F25AF3E18ACF2BD27C 史蒂文 C9A3AB53FAA9E8243A63EBDC3257D1C8CCEC7D1C 凯文 D7C6774E65DBB8F312F50183C87D67BC6FBF7BED 加文 F4C1945162294DD902C6BC11EE23BF8B682AC6C9 卢克 DF2FD780E13F9511411EC92B476D167A6D9F334A 马丁 FE6D5175D3B6E49B6649DBD6F21559F15847CA31 pippo DA908468DBE291E4DDEB082E36E9F5BB316A3C3C 理查德 EC26FF6B364C51DCA5A7CB5D711BCC85946D2517 特洛伊 F1165BE81E08B38A42C582A8F25C2CC382233F3D 扎克 EF19BED4FD6732C92437A3F65C4BE69A5010994D 威廉 EC74AA8C93AA32EFF85EC4437F50F1F86AECAC29 查理 C86D2F8A3EF1F03127628C7CF9C6D9FB730DACBF
我只是从 main 调用 alice() 来测试这个。
【问题讨论】:
-
除了实际代码之外,您的问题还缺少您使用的加密库的信息。请同时添加。
-
由于您仍在学习 C,您可能需要先完成学习方面。编写没有所有加密内容的代码,看看您是否可以正确使用字符串。并且您完全了解如何使用数组和指针。然后回到这个加密/解密练习!
-
注意:
' '和'\n'不是必需的。在fscanf(fp,"%s %s\n",....也许fscanf(fp,"%127s%127s",....除非你需要128 个字符串,在这种情况下char buffer1[128+1], buffer2[128+1]; fscanf(fp,"%128s%128s",.... -
我设法找出了我的严重错误。该行:AES_set_encrypt_key(k_j, sizeof(k_j), &enc_key);应该是:AES_set_encrypt_key(k_j, sizeof(k_j)*8, &enc_key); AES_CBC_Encrypt() 函数中的 enclength 和 declength 显然应该相同。所以我用 48bytes 加密和解密,否则对我不起作用。我可能是错的,但是当我使用 strlen(buffer2) 进行加密(即 40 字节)时,解密只能正确解密部分字符串,其余部分仍然是乱码。
标签: c string openssl aes encryption-symmetric