在 PHP 中加密,在 C 中解密
Encrypt in PHP, decrypt in C
我想在 PHP 中加密一个字符串,然后在 C 中解密它。我卡在解密部分了。
(PHP) 我先加密字符串:
function encrypt($plaintext, $key) {
$iv = 'aaaaaaaaaaaaaaaa';
$ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
return $ciphertext;
}
echo encrypt('This is a test', 'test');
// output: 7q�7h_��8� ��L
(C) 然后我想解密它,我使用 tiny-AES-c 函数库:
int test_decrypt_cbc(void) {
uint8_t key[] = "test";
uint8_t iv[] = "aaaaaaaaaaaaaaaa";
uint8_t str[] = "7q�7h_��8� ��L";
printf("%s", str);
printf("\n Decrypted buffer\n");
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, str, sizeof(str));
printf("%s", str);
printf("\n");
return 1;
}
这输出:
7q�7h_��8� ��L
Decrypted buffer
?L??Ɵ??m??Dˍ?'?&??c?W
它应该输出“这是一个测试”。
我该如何解决这个问题?
在PHP代码中,使用了AES-256。 tiny-AES-c 默认只支持 AES-128。为了支持 AES-256,必须在 aes.h 中定义相应的常量,即必须在 here.
中注释行 //#define AES256 1
PHP 默认使用 PKCS7 填充。应在 C 代码中删除填充。
PHP 隐式地用零值将太短的键填充到指定的长度。由于PHP代码中指定了AES-256-CBC,所以密钥测试扩展如下:
test[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]
在 C 代码中必须使用此扩展密钥(另请参阅@r3mainer 的评论)。
为了在两个代码之间传输密文,必须使用合适的编码,例如Base64 或十六进制(另请参阅@Ôrel 的评论)。对于后者,可以将bin2hex
应用于PHP代码中的密文。可以在 here.
中找到 C 中十六进制解码的示例
一个可能的 C 实现是:
// Pad the key with zero values
uint8_t key[] = "test[=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=]";
uint8_t iv[] = "aaaaaaaaaaaaaaaa";
uint8_t ciphertextHex[] = "3771e837685ff5d4173801900de6e14c";
// Hex decode (e.g.
uint8_t ciphertext[sizeof(ciphertextHex) / 2], * pos = ciphertextHex;
for (size_t count = 0; count < sizeof ciphertext / sizeof * ciphertext; count++) {
sscanf((const char*)pos, "%2hhx", &ciphertext[count]);
pos += 2;
}
// Decrypt
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, ciphertext, sizeof(ciphertext));
// Remove the PKCS7 padding
uint8_t ciphertextLength = sizeof(ciphertext);
uint8_t numberOfPaddingBytes = ciphertext[ciphertextLength - 1];
ciphertext[ciphertextLength - numberOfPaddingBytes] = 0;
printf("%s", ciphertext);
我想在 PHP 中加密一个字符串,然后在 C 中解密它。我卡在解密部分了。
(PHP) 我先加密字符串:
function encrypt($plaintext, $key) {
$iv = 'aaaaaaaaaaaaaaaa';
$ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv);
return $ciphertext;
}
echo encrypt('This is a test', 'test');
// output: 7q�7h_��8� ��L
(C) 然后我想解密它,我使用 tiny-AES-c 函数库:
int test_decrypt_cbc(void) {
uint8_t key[] = "test";
uint8_t iv[] = "aaaaaaaaaaaaaaaa";
uint8_t str[] = "7q�7h_��8� ��L";
printf("%s", str);
printf("\n Decrypted buffer\n");
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, str, sizeof(str));
printf("%s", str);
printf("\n");
return 1;
}
这输出:
7q�7h_��8� ��L
Decrypted buffer
?L??Ɵ??m??Dˍ?'?&??c?W
它应该输出“这是一个测试”。
我该如何解决这个问题?
在PHP代码中,使用了AES-256。 tiny-AES-c 默认只支持 AES-128。为了支持 AES-256,必须在 aes.h 中定义相应的常量,即必须在 here.
中注释行//#define AES256 1
PHP 默认使用 PKCS7 填充。应在 C 代码中删除填充。
PHP 隐式地用零值将太短的键填充到指定的长度。由于PHP代码中指定了AES-256-CBC,所以密钥测试扩展如下:
test[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]
在 C 代码中必须使用此扩展密钥(另请参阅@r3mainer 的评论)。
为了在两个代码之间传输密文,必须使用合适的编码,例如Base64 或十六进制(另请参阅@Ôrel 的评论)。对于后者,可以将
中找到 C 中十六进制解码的示例bin2hex
应用于PHP代码中的密文。可以在 here.一个可能的 C 实现是:
// Pad the key with zero values uint8_t key[] = "test[=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=]"; uint8_t iv[] = "aaaaaaaaaaaaaaaa"; uint8_t ciphertextHex[] = "3771e837685ff5d4173801900de6e14c"; // Hex decode (e.g. uint8_t ciphertext[sizeof(ciphertextHex) / 2], * pos = ciphertextHex; for (size_t count = 0; count < sizeof ciphertext / sizeof * ciphertext; count++) { sscanf((const char*)pos, "%2hhx", &ciphertext[count]); pos += 2; } // Decrypt struct AES_ctx ctx; AES_init_ctx_iv(&ctx, key, iv); AES_CBC_decrypt_buffer(&ctx, ciphertext, sizeof(ciphertext)); // Remove the PKCS7 padding uint8_t ciphertextLength = sizeof(ciphertext); uint8_t numberOfPaddingBytes = ciphertext[ciphertextLength - 1]; ciphertext[ciphertextLength - numberOfPaddingBytes] = 0; printf("%s", ciphertext);