openssl3.2 - exp - base64 / unbase64

文章目录

openssl3.2 - exp - base64 / unbase64

概述

想将2进制内容放到配置文件中, 作为配置项的值.

那先base64一下, 变成可见字符串后再写入配置文件.

先看了官方的命令行实现.

然后从官方命令行实现, 迁移出一个调用openssl API来干活的版本.

自己测试迁移后的版本时, 细节还是挺多, 不像记录官方实现那么容易.

对BIO_push()的使用有了进一步的认识.

笔记

命令行实现

c 复制代码
// 做实验用的明文
echo this is pt > pt.txt

// base64帮助
openssl base64 --help

// base64 明文编码
openssl base64 -e -in pt.txt -out pt.txt.base64

// 查看编码后的密文
more pt.txt.base64

// base64 密文解码
openssl base64 -d -in pt.txt.base64 -out pt.txt.base64.unbase64

// 查看解码后的明文
more pt.txt.base64.unbase64

程序实现

c 复制代码
/*!
* \file exp033_base64.cpp
* \note openssl3.2 - exp - base64 / unbase64
* 用BIO链来完成base64/unbase64
*/

#include "my_openSSL_lib.h"
#include <openssl/crypto.h>
#include <openssl/bio.h>

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "CMemHookRec.h"

#include <openssl/evp.h>

void my_openssl_app();
bool base64(bool isEncode, UCHAR* pucBufIn, int lenBufIn, UCHAR*& pucBufOut, int& lenBufOut);

int main(int argc, char** argv)
{
	setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞
	mem_hook();

	my_openssl_app();

	mem_unhook();

	/*! run result
	buffer original
	0000 - 00 01 02 03 04 05 06 07-08 09 0a 0b 0c            .............
	after base64
	0000 - 41 41 45 43 41 77 51 46-42 67 63 49 43 51 6f 4c   AAECAwQFBgcICQoL
	0010 - 44 41 3d 3d 0a                                    DA==.
	after unbase64
	0000 - 00 01 02 03 04 05 06 07-08 09 0a 0b 0c            .............
	ok : the same by org and unbase64
	free map, g_mem_hook_map.size() = 0

	D:\my_dev\my_local_git_prj\study\openSSL\exp\exp033_base64\x64\Debug\exp033_base64.exe (进程 305792)已退出,代码为 0。
	要在调试停止时自动关闭控制台,请启用"工具"->"选项"->"调试"->"调试停止时自动关闭控制台"。
	按任意键关闭此窗口. . .
	*/

	return 0;
}

void my_openssl_app()
{
	int i = 0;
	UCHAR ucBuf[0x10 - 3];

	UCHAR* pucBufOut = NULL;
	int iLenBufOut = 0;

	UCHAR* pucBufOut1 = NULL;
	int iLenBufOut1 = 0;

	for (i = 0; i < sizeof(ucBuf); i++)
	{
		ucBuf[i] = (UCHAR)i;
	}

	printf("buffer original\n");
	BIO_dump_fp(stdout, ucBuf, sizeof(ucBuf));

	do {
		if (!base64(true, ucBuf, sizeof(ucBuf), pucBufOut, iLenBufOut))
		{
			assert(false);
			break;
		}

		printf("after base64\n");
		BIO_dump_fp(stdout, pucBufOut, iLenBufOut);

		if (!base64(false, pucBufOut, iLenBufOut, pucBufOut1, iLenBufOut1))
		{
			assert(false);
			break;
		}

		printf("after unbase64\n");
		BIO_dump_fp(stdout, pucBufOut1, iLenBufOut1);

		if (iLenBufOut1 != sizeof(ucBuf))
		{
			assert(false);
			break;
		}

		if (0 != memcmp(ucBuf, pucBufOut1, sizeof(ucBuf)))
		{
			assert(false);
			break;
		}

		printf("ok : the same by org and unbase64\n");

	} while (false);

	if (NULL != pucBufOut)
	{
		OPENSSL_free(pucBufOut);
		pucBufOut = NULL;
	}

	if (NULL != pucBufOut1)
	{
		OPENSSL_free(pucBufOut1);
		pucBufOut1 = NULL;
	}
}

bool base64(bool isEncode, UCHAR* pucBufIn, int lenBufIn, UCHAR*& pucBufOut, int& lenBufOut)
{
	bool b_rc = false;
	BIO* bio_container = NULL;
	BIO* bio_to_base64 = NULL;

	BIO* bio_header = NULL; // BIO链头
	BIO* bio_tail = NULL; // BIO链尾

	BIO* bio_to_write = NULL; // 将数据写入的BIO指针
	BIO* bio_read_from = NULL; // 将数据读出的BIO指针

	size_t sz_wt = 0;
	size_t sz_rd = 0;
	int i_rc = 0;
	int len = 0;

	do {
		pucBufOut = NULL;
		lenBufOut = 0;
		if ((NULL == pucBufIn) || (lenBufIn <= 0))
		{
			break;
		}

		bio_container = BIO_new(BIO_s_mem());
		if (NULL == bio_container)
		{
			break;
		}

		bio_to_base64 = BIO_new(BIO_f_base64());
		if (NULL == bio_to_base64)
		{
			break;
		}

		bio_header = BIO_push(bio_to_base64, bio_container);
		bio_tail = bio_container;

		if (isEncode)
		{
			bio_to_write = bio_header;
			bio_read_from = bio_tail;
		}
		else {
			bio_to_write = bio_tail;
			bio_read_from = bio_header;
		}

		i_rc = BIO_write_ex(bio_to_write, pucBufIn, lenBufIn, &sz_wt);
		if ((1 != i_rc) || (lenBufIn != sz_wt))
		{
			break;
		}

		BIO_flush(bio_to_write); // 数据写完后, 必须对写入的BIO执行 BIO_flush.

		// 必须从bio_read_from读取处理完的数据长度, 才是处理之后的数据长度
		len = BIO_pending(bio_read_from); // 必须BIO_flush()之后, 才能读取到BIO内可以读出的数据长度. 否则读出的长度是0
		// 当解码时, 得到的处理完的长度还是没解码之前的长度, 不过不影响
		// 拿这个长度开buffer, 实际数据处理完的长度按照从bio_read_from()中累计出的数据长度为准

		// 将处理过的数据从bio_header中读出来
		pucBufOut = (UCHAR*)OPENSSL_malloc(len + 1); // 再多加1个字节的空间, 便于观察得到的可见字符串
		if (NULL == pucBufOut)
		{
			break;
		}
		
		pucBufOut[len] = '\0';

		do {
			// 不能从bio_header读取, 因为读取后, 还是原来的数据长度
			i_rc = BIO_read_ex(bio_read_from, pucBufOut + lenBufOut, len - lenBufOut, &sz_rd);
			if (i_rc <= 0)
			{
				// 多次读, 直到读空了, 不算错
				break;
			}

			lenBufOut += sz_rd;
		} while (true);

		b_rc = true;
	} while (false);

	if (NULL != bio_header)
	{
		BIO_free_all(bio_header);
		bio_header = NULL;
	}

	return b_rc;
}

END

相关推荐
紫火桑葚10 天前
windows openssl编译x64版libssl.lib,编译x64版本libcurl.lib,支持https,vs2015编译器
windows·网络协议·https·静态库·openssl·libcurl
花落已飘18 天前
openssl中的SM3
c语言·算法·哈希算法·openssl
花落已飘1 个月前
openssl使用哈希算法生成随机密钥
算法·哈希算法·openssl
花落已飘1 个月前
openssl哈希算法
算法·哈希算法·openssl
zwm_yy1 个月前
openssl生成ca证书
openssl·ca
甄齐才1 个月前
解决windows下php8.x及以上版本,在Apache2.4中无法加载CURL扩展的问题
php·openssl·php7.4·php8开启curl扩展·system32·dynamic library·php_curl.dll
胡西风_foxww1 个月前
Linux下编译安装Nginx
linux·运维·nginx·编译·安装·openssl·pcre
Ho_pe1 个月前
ubuntu下openssl签名证书制作流程及验证demo
服务器·ubuntu·openssl
花落已飘2 个月前
openssl对称加密代码讲解实战
加密·openssl
花落已飘2 个月前
openssl加密算法简介
加密·openssl