我正在研究客户端-服务器通信,并致力于确保双方提供相同的加密 token 值。无法弄清楚为什么它们不同。 key 和初始化 vector 以及消息本身都是相同的。
这是在客户端代码中进行加密的函数:
int main()
{
try
{
std::string message = "HelloWorld";
while ((message.size() & 0xf) != 0xf)
message += " ";
size_t inputslength = message.length();
unsigned char aes_input[inputslength];
memset(aes_input, 0, inputslength/8);
strcpy((char*) aes_input, message.c_str());
unsigned char iv[] = {'0','f','9','3','8','7','b','3','f','9','4','b','f','0','6','f'};
unsigned char aes_key[] = {'Z','T','k','0','Y','T','U','5','Y','j','N','h','M','j','k','4','N','G','I','3','N','m','I','x','N','W','E','x','N','z','d','i'};
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, AES_KEYLENGTH, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, AES_KEYLENGTH, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv, AES_DECRYPT);
printf("original:\t");
hex_print(aes_input, sizeof(aes_input));
printf("encrypt:\t");
hex_print(enc_out, sizeof(enc_out));
printf("decrypt:\t");
hex_print(dec_out, sizeof(dec_out));
std::stringstream ss;
for(int i = 0; i < encslength; i++)
{
ss << enc_out[i];
}
return 0;
}
}
输出
original: 48 65 6C 6C 6F 57 6F 72 6C 64 20 20 20 20 20
encrypt: 72 70 A2 0D FB A1 65 15 17 97 6E 5D 36 23 E2 FA
decrypt: 0A 73 F7 52 AC C1 68 54 1D CA 7A 1F 70 33 F4
同时..在服务器上:
function encryptToken(token)
{
const iv = '0f9387b3f94bf06f';
const key = 'ZTk0YTU5YjNhMjk4NGI3NmIxNWExNzdi';
console.log("key len: " + key.length);
const encrypt = (value) => {
const cipher = crypto.createCipheriv('AES-256-CBC', key, iv);
let encrypted = cipher.update(value, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
};
console.log('Encrypteddd value: ', encrypt('HelloWorld'));
}
输出
Encrypteddd value: 0c491f8c5256b9744550688fc54926e8
在尝试 CBC-256 加密之前,我尝试了更简单的加密模式 ECB-128,这一切都归结为同样的问题。客户端和服务器端生成不同的加密 token ,导致无法解密来自服务器端的内容。任何集思广益的技巧都会有所帮助。我已经没有想法了,谢谢。
更新 12.26 -
在客户端获取有关初始化 vector 和数组长度的建议后..这是我更新的代码及其输出:
int main()
{
try
{
std::string message = "HelloWorld";
while ((message.size() & 0xf) != 0xf)
message += " ";
size_t inputslength = message.length();
unsigned char aes_input[inputslength+1];
memset(aes_input, 0, inputslength/8);
strcpy((char*) aes_input, message.c_str());
unsigned char iv[] = {0x0f, 0x93, 0x87, 0xb3, 0xf9, 0x4b, 0xf0, 0x6f};
unsigned char aes_key[] = {'Z','T','k','0','Y','T','U','5','Y','j','N','h','M','j','k','4','N','G','I','3','N','m','I','x','N','W','E','x','N','z','d','i'};
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, AES_KEYLENGTH, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, AES_KEYLENGTH, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv, AES_DECRYPT);
printf("original:\t");
hex_print(aes_input, sizeof(aes_input));
printf("encrypt:\t");
hex_print(enc_out, sizeof(enc_out));
printf("decrypt:\t");
hex_print(dec_out, sizeof(dec_out));
std::stringstream ss;
for(int i = 0; i < encslength; i++)
{
ss << enc_out[i];
}
return 0;
}
}
//Output:
original: 48 65 6C 6C 6F 57 6F 72 6C 64 00
encrypt: 54 CD 98 20 59 D9 7B 2D D4 23 ED EC D0 13 97 59
Nodejs 代码没有改变,这仍然是输出:
Encrypteddd value: 0c491f8c5256b9744550688fc54926e8
最佳答案
所以,事情就是这样。每次调用 AES_cbc_encrypt
都会更改初始化 vector 的值。他们这样做是为了让您可以链接对 AES_*_encrypt
的调用并处理大于一个 block 的消息。但由于加密调用更改了 iv
的值,因此解密调用将获得不同的初始化 vector 。
一个(糟糕的)解决方案是创建两个 vector :
unsigned char iv_encrypt[] = { /* stuff */ };
unsigned char iv_decrypt[] = { /* same stuff */ };
这样您就可以将相同的数据传递给每个 AES_cbc_encrypt
调用。这至少表明您可以解密原始数据。实现目标的更好、灵活的方法是为每次调用使用初始化 vector 的克隆。像这样的东西:
unsigned char iv[] = { /* stuff */ };
unsigned char *tmp_iv = static_cast<unsigned char*>( malloc( sizeof( iv ) ) );
...
memcpy( tmp_iv, iv, sizeof(iv) );
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, tmp_iv, AES_ENCRYPT);
...
memcpy( tmp_iv, iv, sizeof(iv) );
AES_cbc_encrypt(enc_out, dec_out, inputslength, &dec_key, tmp_iv, AES_DECRYPT);
关于c++ - 在 NodeJS 与 OpenSSL C++ 中加密时获取不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53918059/