首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >base64直接用OpenSSL编码文件,将BIO文件输入链接到based64解码器

base64直接用OpenSSL编码文件,将BIO文件输入链接到based64解码器
EN

Stack Overflow用户
提问于 2022-03-05 21:32:07
回答 2查看 286关注 0票数 1

我想用base64编码非常小的文件(小于缓冲区)。是的,我知道,有很多base64源代码可用,但我想使用OpenSSL。

我的工作例子:

代码语言:javascript
复制
BIO *bin = BIO_new_file("smallfile.bin", "r");
BIO *b64 = BIO_new(BIO_f_base64());
BIO *bmem = BIO_new(BIO_s_mem());
BIO_push(b64, bmem);
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

char buff[8192];
int n=BIO_read(bin, buff, sizeof(buff));
BIO_write(b64, buff, n);
BIO_flush(b64);

n = BIO_read(bmem, buff, sizeof(buff));
cout << string(buff,n) << endl;

BIO_free_all(bin);
BIO_free_all(b64);

如何使链直接读取/写入BIOs,例如: BIO_f_new_file -> BIO_f_base64 ->缓冲区或BIO_s_mem

有可能吗?

EN

回答 2

Stack Overflow用户

发布于 2022-03-06 01:57:38

似乎不可能将源(BIO_s_file)和接收器(BIO_s_mem)组合在一个BIOs链中。它可能需要一个OpenSSL事件循环,因为它不知道需要多少读取才能使用来自源的所有数据。

然而,使用OpenSSL函数对数据进行Base64编码的一个更简单的方法是使用EVP接口

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/evp.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s filename\n", argv[0]);
    return EXIT_FAILURE;
  }

  FILE *fin = fopen(argv[1], "r");
  if (!fin) {
    fprintf(stderr, "Unable to open %s\n", argv[1]);
    return EXIT_FAILURE;
  }

  unsigned char inbuff[8192];
  int insize = fread(inbuff, 1, sizeof inbuff, fin);
  fclose(fin);

  // For every 3 bytes of input provided 4 bytes of output data will be produced. 
  // (Plus a trailing nul)
  int outsize = 4 * (insize/3 + 1) + 1;
  unsigned char outbuff[outsize];
  outsize = EVP_EncodeBlock(outbuff, inbuff, insize);
  if (outsize < 0) {
      fputs("Encoding error!\n", stderr);
      return EXIT_FAILURE;
  }
  fwrite(outbuff, 1, outsize, stdout);
  putchar('\n');
  return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2022-03-08 01:13:47

回答你的问题,这是不可能的生物。迟早,要从BIO链中提取/推送数据,将需要BIO_read/ part。简单地说,你所拥有的基本上是关于它是如何做的。

话虽如此,但有一点值得一提:您不必通过BIO_read操作将数据从内存BIO中提取出来。它已经在那里,只是等待采取,使用BIO_get_mem_data。一个例子比我刚才说的更能说明这一点,所以.

代码语言:javascript
复制
// like you did before...
char buff[8192];
int n=BIO_read(bin, buff, sizeof buff);
BIO_write(b64, buff, n);
BIO_flush(b64);

// ...but do this to get the final data
char *ptr = NULL;
long len = BIO_get_mem_data(bmem, &ptr);

注:未完成内存bio回显int buff的读取。从那里开始,如果您希望数据作为std::string,那么它非常简单,如:

代码语言:javascript
复制
std::string s(ptr, ptr+len);

如果您只想将其转储到std:cout (或任何std::ostream&),则只需使用write流方法,而不需要中间字符串对象:

代码语言:javascript
复制
std::cout.write(ptr, len);

Fwiw,这是我经常将二进制数据转换为C++ std::string对象的方式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71366090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档