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

相关推荐
Lazy Dave11 小时前
gmssl私钥文件格式
网络安全·ssl·openssl
沉在嵌入式的鱼18 天前
RK3588移植Openssl库
linux·rk3588·openssl
黑屋里的马21 天前
ssl相关命令生成证书
服务器·网络·ssl·openssl·gmssl
fangeqin1 个月前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
API开发2 个月前
苹果芯片macOS安装版Homebrew(亲测) ,一键安装node、python、vscode等,比绿色软件还干净、无污染
vscode·python·docker·nodejs·openssl·brew·homebrew
码农不惑2 个月前
Rust使用tokio(二)HTTPS相关
https·rust·web·openssl
liulilittle2 个月前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法并通过OPENSSL加密验证算法正确性。
linux·服务器·c++·算法·安全·加密·openssl
liulilittle2 个月前
OpenSSL 的 AES-NI 支持机制
linux·运维·服务器·算法·加密·openssl·解密
liulilittle2 个月前
通过高级处理器硬件指令集AES-NI实现AES-256-CFB算法。
linux·服务器·c++·算法·安全·加密·openssl
花花少年2 个月前
Ubuntu系统下交叉编译openssl
openssl·交叉编译