在循环内连接 unsigned char *
Concatenate unsigned char * inside a loop
我正在使用 OpenSSL 库通过 AES 进行加密。由于 AES 是分组密码,我需要将数据分成 16 字节的块。因此,如果我想恢复消息,我需要在程序结束时合并这些块。
这是我的代码:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey123";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
int i;
int k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
in[160] = '[=10=]';
printf("IN:%s\n", in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
text_slice[0] = '[=10=]';
enc_slice[0] = "[=10=]";
dec_slice[0] = "[=10=]";
memcpy(&text_slice[0], &in[15 * i], 15);
text_slice[16] = "[=10=]";
printf("TEXT SLICE: %s \n", text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], &enc_slice[0], 16);
}
printf("ENC:%s\n", enc_out);
for (i = 0; i < k; i++) {
text_slice[0] = '[=10=]';
enc_slice[0] = "[=10=]";
dec_slice[0] = "[=10=]";
memcpy(enc_slice, &enc_out[16 * i], 16);
enc_slice[16] = "[=10=]";
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice:%s \n", dec_slice);
memcpy(&dec_out[16 * i], &dec_slice[0], 16);
}
printf("DEC OUT:%s\n", dec_out);
return 0;
}
程序的输出如下:
IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ
TEXT SLICE: OWKKYHIDDQSCDXR
TEXT SLICE: JMOWFRXSJYBLDBE
TEXT SLICE: FSARCBYNECDYGGX
TEXT SLICE: XPKLORELLNMPAPQ
TEXT SLICE: FWKHOPKMCOQHNWN
TEXT SLICE: KUEWHSQMGBBUQCL
TEXT SLICE: JJIVSWMDKQTBXIX
TEXT SLICE: MVTRRBLJPTNSNFW
TEXT SLICE: ZQFJMAFADRRWSOF
ENC:j�Q���
�7֡���*n���R ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ
Dec slice:OWKKYHIDDQSCDXR
Dec slice:JMOWFRXSJYBLDBE
Dec slice:FSARCBYNECDYGGX
Dec slice:XPKLORELLNMPAPQ
Dec slice:FWKHOPKMCOQHNWN
Dec slice:KUEWHSQMGBBUQCL
Dec slice:JJIVSWMDKQTBXIX
Dec slice:MVTRRBLJPTNSNFW
Dec slice:ZQFJMAFADRRWSOF
DEC OUT:NWLRBBMQBHCDARZ
虽然 dec_slice
按预期工作,但 dec_out
只是获取第一个块的内存副本。更令我惊讶的是,enc_out
在遵循与 dec_out
相同的逻辑时正确执行。我错过了什么?
密钥必须至少有 16 个字节,因为您传递的位数等于 128:
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
你在这里有未定义的行为:
in[160] = '[=11=]';
这些行没有意义:
enc_slice[0] = "[=12=]";
dec_slice[0] = "[=12=]";
text_slice[16] = "[=12=]";
enc_slice[16] = "[=12=]";
为什么要对 15 个字符而不是 16 个字符的块进行编码?
memcpy(&text_slice[0], &in[15 * i], 15);
这是修改后的版本:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey1234567";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160];
unsigned char dec_out[160];
int i, k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
printf("IN: \"%.160s\"\n", (char *)in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
memcpy(text_slice, &in[16 * i], 16);
printf("TEXT SLICE: %.16s\n", (char *)text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], enc_slice, 16);
}
printf("ENC:");
for (i = 0; i < 16 * k; i++) {
printf(" %02X\n", enc_out[i]);
}
printf("\n");
for (i = 0; i < k; i++) {
memcpy(enc_slice, &enc_out[16 * i], 16);
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice: %.16s \n", (char *)dec_slice);
memcpy(&dec_out[16 * i], dec_slice, 16);
}
printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
return 0;
}
那个代码有很多问题。
AES_set_encrypt_key
和AES_set_decrypt_key
不是密钥推导函数,第二个参数应该表示第一个参数(userKey
)的位长度。
如果您提供长度不是 128 位的任意字符串常量,如 "secretkey123"
,它可能会导致内存损坏或为您的加密创建一个非常不安全的上下文。
一般来说,对于基于用户密码的加密,我们使用密钥派生函数从任何密码生成密钥(例如PBKDF2
,或scrypt
)。
这行也不好:
in[160] = '[=10=]';
由于缓冲区的大小为 160
,因此最后一个索引应为 160 - 1
。如果你在索引 160
处写入,你实际上是溢出了。
还有,写C代码的时候一定要注意单引号和双引号的区别
这很糟糕:
enc_slice[0] = "[=11=]";
dec_slice[0] = "[=11=]";
如果您使用双引号,您实际上并不是在 enc_slice
和 dec_slice
的第一个索引处写入值 0
。您正在写入空 read-only 常量字符串的地址。
还有这个:
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
如果你想要空缓冲区,你应该这样做:
unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};
希望这是改进代码并使其正常工作的良好开端。
我正在使用 OpenSSL 库通过 AES 进行加密。由于 AES 是分组密码,我需要将数据分成 16 字节的块。因此,如果我想恢复消息,我需要在程序结束时合并这些块。
这是我的代码:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey123";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
int i;
int k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
in[160] = '[=10=]';
printf("IN:%s\n", in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
text_slice[0] = '[=10=]';
enc_slice[0] = "[=10=]";
dec_slice[0] = "[=10=]";
memcpy(&text_slice[0], &in[15 * i], 15);
text_slice[16] = "[=10=]";
printf("TEXT SLICE: %s \n", text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], &enc_slice[0], 16);
}
printf("ENC:%s\n", enc_out);
for (i = 0; i < k; i++) {
text_slice[0] = '[=10=]';
enc_slice[0] = "[=10=]";
dec_slice[0] = "[=10=]";
memcpy(enc_slice, &enc_out[16 * i], 16);
enc_slice[16] = "[=10=]";
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice:%s \n", dec_slice);
memcpy(&dec_out[16 * i], &dec_slice[0], 16);
}
printf("DEC OUT:%s\n", dec_out);
return 0;
}
程序的输出如下:
IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ
TEXT SLICE: OWKKYHIDDQSCDXR
TEXT SLICE: JMOWFRXSJYBLDBE
TEXT SLICE: FSARCBYNECDYGGX
TEXT SLICE: XPKLORELLNMPAPQ
TEXT SLICE: FWKHOPKMCOQHNWN
TEXT SLICE: KUEWHSQMGBBUQCL
TEXT SLICE: JJIVSWMDKQTBXIX
TEXT SLICE: MVTRRBLJPTNSNFW
TEXT SLICE: ZQFJMAFADRRWSOF
ENC:j�Q���
�7֡���*n���R ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ
Dec slice:OWKKYHIDDQSCDXR
Dec slice:JMOWFRXSJYBLDBE
Dec slice:FSARCBYNECDYGGX
Dec slice:XPKLORELLNMPAPQ
Dec slice:FWKHOPKMCOQHNWN
Dec slice:KUEWHSQMGBBUQCL
Dec slice:JJIVSWMDKQTBXIX
Dec slice:MVTRRBLJPTNSNFW
Dec slice:ZQFJMAFADRRWSOF
DEC OUT:NWLRBBMQBHCDARZ
虽然 dec_slice
按预期工作,但 dec_out
只是获取第一个块的内存副本。更令我惊讶的是,enc_out
在遵循与 dec_out
相同的逻辑时正确执行。我错过了什么?
密钥必须至少有 16 个字节,因为您传递的位数等于 128:
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
你在这里有未定义的行为:
in[160] = '[=11=]';
这些行没有意义:
enc_slice[0] = "[=12=]";
dec_slice[0] = "[=12=]";
text_slice[16] = "[=12=]";
enc_slice[16] = "[=12=]";
为什么要对 15 个字符而不是 16 个字符的块进行编码?
memcpy(&text_slice[0], &in[15 * i], 15);
这是修改后的版本:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey1234567";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160];
unsigned char dec_out[160];
int i, k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
printf("IN: \"%.160s\"\n", (char *)in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
memcpy(text_slice, &in[16 * i], 16);
printf("TEXT SLICE: %.16s\n", (char *)text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], enc_slice, 16);
}
printf("ENC:");
for (i = 0; i < 16 * k; i++) {
printf(" %02X\n", enc_out[i]);
}
printf("\n");
for (i = 0; i < k; i++) {
memcpy(enc_slice, &enc_out[16 * i], 16);
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice: %.16s \n", (char *)dec_slice);
memcpy(&dec_out[16 * i], dec_slice, 16);
}
printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
return 0;
}
那个代码有很多问题。
AES_set_encrypt_key
和AES_set_decrypt_key
不是密钥推导函数,第二个参数应该表示第一个参数(userKey
)的位长度。
如果您提供长度不是 128 位的任意字符串常量,如 "secretkey123"
,它可能会导致内存损坏或为您的加密创建一个非常不安全的上下文。
一般来说,对于基于用户密码的加密,我们使用密钥派生函数从任何密码生成密钥(例如PBKDF2
,或scrypt
)。
这行也不好:
in[160] = '[=10=]';
由于缓冲区的大小为 160
,因此最后一个索引应为 160 - 1
。如果你在索引 160
处写入,你实际上是溢出了。
还有,写C代码的时候一定要注意单引号和双引号的区别
这很糟糕:
enc_slice[0] = "[=11=]";
dec_slice[0] = "[=11=]";
如果您使用双引号,您实际上并不是在 enc_slice
和 dec_slice
的第一个索引处写入值 0
。您正在写入空 read-only 常量字符串的地址。
还有这个:
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
如果你想要空缓冲区,你应该这样做:
unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};
希望这是改进代码并使其正常工作的良好开端。