C++中如何使用cURL发送序列化后的Ciphertext对象
C++ 结合SEAL与cURL传输序列化Ciphertext的截断问题解决方案
问题根因
你的猜测完全正确:
Microsoft SEAL的Ciphertext序列化结果为二进制字节流,内部天然存在大量
\0空字节。c_str()/data()返回的指针本身指向完整数据的首地址,但C风格字符串的默认处理规则以\0作为结束标记,因此所有依赖C字符串长度计算的逻辑都会在第一个\0位置直接截断数据,你遇到的长度从88500变为6的表现,恰好说明第7个字节是\0。
另外你当前的写法还存在悬垂指针风险:st.str()会生成一个临时std::string对象,调用c_str()后临时对象立即销毁,simplePost拿到的指针指向已经被回收的内存,即使没有截断问题也会引发随机崩溃。
修复方案
方案1:传输原始二进制流(推荐,性能最优)
- 调整你封装的
simplePost接口,新增长度参数,不再依赖C字符串结束符判断数据长度:
// 原接口(不支持二进制):int simplePost(const char* path, const char* data); // 调整后接口: int simplePost(const char* path, const char* data, size_t data_len);
- 调用时先将序列化结果存为局部
std::string,避免临时对象销毁:
std::stringstream st; cipheredAspirineList[0].save(st); std::string serial_cipher = st.str(); simplePost("postSingleCipheredAspirine", serial_cipher.data(), serial_cipher.size());
- cURL请求配置新增长度指定和对应请求头:
// 内部cURL配置参考 CURL* curl = curl_easy_init(); struct curl_slist* headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/octet-stream"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); // 显式指定数据总长度,避免cURL自动按C字符串截断 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)data_len);
方案2:Base64编码后传输(兼容性高)
如果无法修改simplePost接口,或者服务端要求只能接收文本格式数据,可以先将序列化后的二进制数据做Base64编码,转成全可打印字符的字符串后再传输,此时不会出现\0截断问题,仅会增加约33%的数据体积,服务端收到后做Base64解码再反序列化即可。
内容的提问来源于stack exchange,提问作者dsimog01
相关产品推荐
相关产品推荐

