使用openssl BIO逐块进行base64解码
Posted
技术标签:
【中文标题】使用openssl BIO逐块进行base64解码【英文标题】:base64 decode with openssl BIO block by block 【发布时间】:2017-04-21 10:35:40 【问题描述】:我在使用以下代码解码 base64 编码数据时遇到问题。我有大约 3.5 MB 的数据要解码。它几乎可以正常工作,直到最后缺少某些东西。
以下代码读取 100 kB 源数据块,将其写入 BIO_s_mem,然后多次读取 1024 字节的解码数据。当没有更多内容可读取时,将检索另一个 100 kB 块并再次使用。在收到最后一个块之前一切正常。它没有完整的 100 kB(只有 25685 字节)。我将它写入 BIO,解码 18 次 1024 字节,然后再解码 435 次,仅此而已。但这还不是全部。仍有大约 100 字节的解码数据无法读取。
正确接收所有编码数据(将它们保存到文件并从 shell 命令手动解码可提供完整输出)。我应该如何从 BIO 获得其余部分?我想我应该以某种方式说这就是全部。例如,我尝试了多种方式 BIO_flush,一些标志,在编码数据中添加换行符,但还没有成功。
BIO *bmem, *b64;
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
BIO_push(b64, bmem);
vector<char> buf(1024);
while (!end)
end = task->nextChunk(chunk, chunkSize); // this reads encoded data block
BIO_write(bmem, (void*)chunk, chunkSize);
cout << "Chunk size: " << chunkSize << endl;
if (end || chunkSize == 0)
BIO_flush(bmem); // I tried multiple things
BIO_flush(b64); // flush here and there, nothing helped
BIO_set_close(bmem, BIO_CLOSE); // and other things... ;-)
string result;
int nread;
while ((nread = BIO_read(b64, buf.data(), buf.size())) > 0)
cout << "Decoded bytes read: " << nread << endl;
result.append(buf.data(), nread);
ret->appendRaw(result.c_str(), result.size()); // store result somehow
最后输出序列:
Chunk size: 25685
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 1024
Decoded bytes read: 435
Chunk size: 0
再说一次:解码后的输出是二进制文件。它已正确编码,正确发送到我的代码,但未解码,最后大约 100 个字节丢失。 感谢您的任何提示。
【问题讨论】:
我 认为(nread = BIO_read(b64, buf.data(), buf.size())) > 0
可能不太正确。我认为对生物执行的测试是do len = BIO_read(b64, ...); while (len > 0 || BIO_should_retry(b64));
但这是针对套接字生物的;我不确定文件或内存生物有何不同。
感谢您的提示。我已经对此进行了实验。当所有块都写入我的 BIO_s_mem 时,从 b64 读取会给出 -1 并且 BIO_should_retry(b64) 保持为真,因此它永远不会结束。这就是为什么我认为我需要以某种方式说“就是这样”,最后一部分将被解码,返回并且循环可以完成。
【参考方案1】:
诀窍在于在最终的 BIO_read 序列之前添加以下两行:
BIO_write(bmem, "\n", 1);
BIO_set_mem_eof_return(bmem, BIO_NOCLOSE);
【讨论】:
以上是关于使用openssl BIO逐块进行base64解码的主要内容,如果未能解决你的问题,请参考以下文章
OpenSSL 使用 base64 编码/解码(liang19890820)