encryption - C++Openssl 截断 JSON 输入
问题描述
我正在开发一个项目,该项目涉及加密一个 json 字符串(4000+ 个字符长),然后在通过 CURL 发布到 PHP 后对其进行解密。我已经让 openssl 库工作和编译,它能够将类似的 json 数据加密保存到二进制文件中,读取它,解密它并使用它。只要我只尝试加密字符串并发布它,openssl 就会截断数据。数据包含特殊字符(utf8mb4),但由于它可以很好地写入文件,我对它为什么拒绝加密整个字符串感到困惑。我使用 32 字节(256 位)密钥和 16 字节(128 位)iv 尝试了以下操作:
AES-256-CBC AES-256-CFB AES-256-ECB AES-256-GCM
较短的字符串可以正常工作(即 < 175 个字符)。但较长的字符串(例如 JSON 有效负载)不起作用。即使是 openssl 自己的示例代码也不加密有效载荷。
主要功能(用于测试):https ://pastebin.com/ZrpSd88W
int main()
{
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Set up the key and iv. Do I need to say to not hard code these in a real application? :-) */
/* A 256 bit key */
static const unsigned char key[] = "01234567890123456789012345678901";
/* A 128 bit IV */
static const unsigned char iv[] = "0123456789012345";
/* Message to be encrypted */
unsigned char plaintext[] = "The quick brown fox jumps over the lazy dog";
/* Some additional data to be authenticated */
static const unsigned char aad[] = "Some AAD data";
int decryptedtext_len = 0, ciphertext_len = 0;
printf("");
printf("");
printf("");
printf("");
printf("");
printf("");
printf("");
curl_global_init(CURL_GLOBAL_ALL);
std::string data = "{ \"jobData\": {\"isMultiplayer\": false,\"late\": false,\"sourceCity\": \"Düsseldorf\",\"sourceCompany\": \"Stokes\",\"destinationCity\": \"Duisburg\",\"destinationCompany\": \"LkwLog GmbH\",\"cargo\": \"Wheat\",\"truckMake\": \"Volvo\",\"truckModel\": \"FH16 Classic\",\"game\": \"Euro Truck Simulator 2\",\"sourceCityID\": \"dusseldorf\",\"sourceCompanyID\": \"stokes\",\"destinationCityID\": \"duisburg\",\"destinationCompanyID\": \"lkwlog\",\"cargoID\": \"wheat\",\"truckMakeID\": \"volvo\",\"truckModelID\": \"vehicle.volvo.fh16\",\"gameID\": \"ets2\",\"gameVersion\": \"1.13\",\"pluginVersion\": \"0.15.365.0\",\"income\": 799,\"trailerMass\": 17140,\"distanceDriven\": 7.56641,\"fuelBurned\": 4.75964,\"fuelPurchased\": 0,\"startOdometer\": 64493,\"endOdometer\": 64500.6,\"collisionCount\": 3,\"finishTrailerDamage\": 0.0201135,\"startTrailerDamage\": 0,\"deliveryX\": -13184.1,\"deliveryY\": 58.2873,\"deliveryZ\": -6147.25,\"pickupX\": -13147.2,\"pickupY\": 48.0304,\"pickupZ\": -4555.74,\"trailerDeliveryX\": -13184.2,\"trailerDeliveryY\": 58.2863,\"trailerDeliveryZ\": -6152.03,\"trailerPickupX\": -13147.2,\"trailerPickupY\": 48.0285,\"trailerPickupZ\": -4560.52,\"startEngineDamage\": 0,\"startTransmissionDamage\": 0,\"startCabinDamage\": 0,\"startChassisDamage\": 0,\"startWheelDamage\": 0,\"finishEngineDamage\": 0.0138086,\"finishTransmissionDamage\": 0.00829076,\"finishCabinDamage\": 0.0220714,\"finishChassisDamage\": 0.0275892,\"finishWheelDamage\": 0.00427838,\"totalEngineDamage\": 0.0138086,\"totalTransmissionDamage\": 0.00829076,\"totalCabinDamage\": 0.0220714,\"totalChassisDamage\": 0.0275892,\"totalWheelDamage\": 0.00427838,\"totalTrailerDamage\": 0.0201135,\"osEnvironment\": \"Windows\",\"architecture\": \"x64\",\"steamID\": \"xxx\",\"steamUsername\": \"xxx\",\"navigationDistanceRemaining\": 160.393,\"teleported\": true}}";
unsigned char a[KEY_SIZE+1];
unsigned char b[IV_SIZE + 1];
for (int i = 0; i < KEY_SIZE; i++)
a[i] = 'a';
for (int i = 0; i < IV_SIZE; i++)
b[i] = 'b';
a[KEY_SIZE] = '\0';
b[IV_SIZE] = '\0';
int predicted_len = strlen(data.c_str()) + (BLOCK_SIZE - (strlen(data.c_str()) % BLOCK_SIZE));
predicted_len = strlen(data.c_str());
unsigned char* encrypted = new unsigned char[predicted_len+1];
std::string hex2 = NewMessage::StrToHex(a);
std::string hex3 = NewMessage::StrToHex(b);
//int encrypted_len = NewMessage::encryptcbc((unsigned char*)data.c_str(), strlen(data.c_str()), a, b, encrypted);
int encrypted_len = NewMessage::encrypt((unsigned char*)data.c_str()+'\0', strlen(data.c_str()), a,b, encrypted);
encrypted[predicted_len] = '\0';
std::string hex = NewMessage::StrToHex(encrypted);
std::cout << std::endl << std::endl << std::endl << std::endl;
std::cout << hex << std::endl;
std::cout << std::endl << std::endl << std::endl << std::endl;
std::cout << hex2;
std::cout << std::endl << std::endl << std::endl << std::endl;
std::cout << hex3;
std::cout << std::endl << std::endl << std::endl << std::endl;
data.clear();
//delete[] encrypted;
/*----------------------------------------------------------------------*/
data = "";
curl_global_cleanup();
/* Remove error strings */
ERR_free_strings();
return 0;
}
加密功能:
int encrypt(unsigned char* plaintext, int plaintext_len, unsigned char* key, unsigned char* iv, unsigned char* ciphertext)
{
EVP_CIPHER_CTX* ctx = NULL;
int len = 0, ciphertext_len = 0;
/* Create and initialise the context */
if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the encryption operation. */
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv))
handleErrors();
if (plaintext)
{
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
}
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
我不知道为什么data
即使 ciphertext_len 返回正确的值也不会完全加密。如果有人能指出我正确的方向,那就太好了。
解决方案
我让它成功运行,另一位 c++ 开发人员帮助我解决了我正在使用的 StrToHex 方法的问题。有问题的方法(固定)发布在下面:
std::string StrToHex(const std::string& in)
{
std::string csHexString;
for (unsigned int i = 0; i < in.size(); i++)
{
char tmp[10];
int len = sprintf(tmp, "%02X", (in[i] & 0xFF));
csHexString += std::string(tmp, len);
}
return csHexString;
}
推荐阅读
- php - 通过AJAX在PHP中插入数组数据
- javascript - 如果文件在一行中有多个使用管道(|)fs模块分隔的数据,如何读取文本文件?
- python - 将过滤器应用于 plt.imshow 时出现轴缩放问题
- sql - 检索 belongsTo 模型时 hasMany 超时
- excel - 在特定单元格中开始计数器循环并在特定单元格中结束
- html - 边框样式不适用于粘性位置元素
- wordpress - Wordpress 对帖子的评论 - function.php hack
- java - 显示带有下一个和上一个按钮的 ArrayList Javafx
- parallel-processing - Julia 中的并行循环 - 不希望在开始之前将工作分开
- python - 可以使用 HTML optgroup 样式的选项分组在 tkinter/ttk 中创建下拉菜单吗?