openssl base64 编、解码

openssl中使用base64编解码 一、使用背景 ​​       最近在写一套加密接口,数字签名校验老是失败,这是因为对称加密和非对称加密后的数据是二进制的,而二进制数据在网络环境中由于途径的路由设备可能对二进制中不可见字符的处理动作不同,这样就可能会在传输中造成错误,因此需要将数据进行base64编码成可见字符。 二、base64介绍 1、概念 ​       base64是一种基于64个可打印字符来 阅读详情

最近项目上需要对一段二进制串进行 base64编码、解码, base64编码、解码的算法并不复杂,自行实现也不会引入太大代价,不过既然openssl 有比较成熟的实现,直接调用库代码自然是比较明智的选择。

   具体实践过程中,遭遇些细节问题,折腾许久,方才搞定,特此记下,便于以后查阅,同时shared给后来人:
   openssl 中 base64编码相关的几个函数如下:
   ----------------- 转载自其它blog,正确性已经过验证 ------------------------------
    编码函数:
 

Ø         EVP_EncodeInit函数

原型:void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);

功能:该函数初始化一个用来进行base64编码的结构,事实上,该函数只是简单设置了结构里面几个常量的长度。

参数:

ctx:base64设备上下文。

Ø         EVP_EncodeUpdate函数

原型:void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,unsigned char *in,int inl);

功能:该函数将参数in里面的inl自己数据拷贝到结构体ctx里面,如果结构体里面有数据,就同时将结构体里面的数据进行BASE64编码并输出到参数out指向的缓存里面,输出数据的长度保存在outl里面。注意,在第一次调用本函数的时候,虽然往结构体里面拷贝数据了,但是结构体ctx里面开始是没有输入数据存在并且输入数据长度不超出ctx内部存储数据的最长限制,就不会有任何数据被进行BASE64编码,也就是说,不会有任何数据输出;但是如果输入数据长度比内部存储的数据长,那么就会输出部分经过BASE64编码的数据。数据输出总是在下一层输入前完成的。

参数:

ctx:base64设备上下文。

out:存放编码后的数据缓冲区。

outl:编码后的数据长度。

in:编码前的数据。

inl:编码前的数据长度。

Ø         EVP_EncodeFinal函数

原型:void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl);

功能:该函数将结构体ctx里面剩余数据进行BASE64编码并写入到参数out里面去,输出数据的长度保存在outl里面。

参数:

ctx:base64设备上下文。

out:存放编码后的数据。

outl:编码后的数据长度。

Ø         EVP_EncodeBlock函数

  原型:int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);

  功能:该函数将参数f里面的字符串里面的n个字节的字符串进行BASE64编码并输出到参数t里面。返回数据的字节长度。事实上,在函数EVP_EncodeUpdate和EVP_EncodeFinal里面就调用了该函数完成BASE64编码功能。

参数:

t:接收编码后的数据缓冲区。

f:编码前的数据。

n:编码前的数据长度。

 

    解码函数:
 
        Ø       EVP_DecodeInit函数

原型:void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);

功能:该函数初始化一个用来进行BASE64解码的数据结构。

参数:

ctx:base64设备上下文。

Ø         EVP_DecodeUpdate函数

原型:int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl,unsigned char *in, int inl);

功能:该函数将参数in里面inl字节的数据拷贝到结构体ctx里面。如果结构体里面已经有数据,那么这些数据就会先进行BASE64解码,然后输出到参数out指向的内存中,输出的字节数保存在参数outl里面。输入数据为满行的数据时,返回为1;如果输入数据是最后一行数据的时候,返回0;返回-1则表明出错了。

参数:

ctx:base64设备上下文。

out:存放解码后的数据缓冲区。

outl:解码后的数据长度。

in:解码前的数据。

inl:解码前的数据长度。

Ø         EVP_DecodeFinal函数

原型:int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl);

功能:该函数将结构体ctx里面剩余的数据进行BASE64解码并输出到参数out指向的内存中,输出数据长度为outl字节。成功返回1,否则返回-1。

参数:

ctx:base64设备上下文。

out:解码后的数据。

outl:解码后的数据长度。

Ø         EVP_DecodeBlock函数

原型:int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);

功能:该函数将字符串f中的n字节数据进行BASE64解码,并输出到t指向的内存中,输出数据长度为outl。成功返回解码的数据长度,返回返回-1。

参数:

t:接收解码后的数据缓冲区。

f:解码前的数据。

       n:解码前的数据长度。
   --------------------- 上述函数声明为转载内容 ---------------------------
   这些函数声明对应声明在头文件 /usr/include/openssl/evp.h 中。(具体路径视安装情况可能略有差异)。
 
   按照base64的算法,任何长度的串编码后长度均未4的倍数, 解码后均未3的倍数。
   理论上,编码(encode)时,如果输入串不是3的倍数,会在后面补0,以保持3的倍数,反映到encode后的串,就是后面对应补了'=', '='在正常base64编码中不会存在,因此,base64解码时有能力去除尾部的'/0'(虽然上述有些函数没有这么干)。
     
    问题1: 直接使用EVP_EncodeBlock(...) / EVP_DecodeBlock(...) 编码、解码,原串经过编码、解码后可能无法还原!---尾部可能会多'/0', 比如:
          '1234'
          --> EVP_EncodeBlock(...) 变为:'MTIzNA=='  
          --> EVP_DecodeBlock(...) 变为:'1234/0/0' 尾部多了两个/0
          当然这对于以/0结尾的字符串是没影响的,对于二进制数据则直接意味着错误!
      为简便起见,我在程序中直接使用了EVP_EncodeBlock /EVP_DecodeBlock 编、解码, 这个问题困扰了很长时间,更无语的是,google、baidu 关于openssl base64编、解码的说明寥寥无几,仅有的相关博文也几乎仅限于api的说明,还被copy来copy去,很多函数原型都不对了!  相关函数的声明头文件中更是一行注释都没有(这个比较ft -,-|| )
     最后在google下 用纯e文搜索才找出点端倪:(一下内容未查阅源码,为e文 论坛上直接摘录、翻译)
      EVP_DecodeBlock内部同样调用EVP_DecodeInit + EVP_DecodeUpdate + Evp_DecodeFinal实现,但是并未处理尾部的'='字符,因此结果字符串长度总是为3的倍数。若要获取精确的正确长度,外部需添加额外代码,类似下面这样:
        while(input_str[--input_str_len] = '=') output_len--;
        return output_len; // 获取实际长度
        实际就是原输入串尾部有几个 '=', decode后输出串的长度减几久ok了。
    问题2: 直接使用EVP_DecodeInit + EVP_DecodeUpdate + EVP_DecodeFinal 组合进行decode是可以处理尾部'='字符,正确获取原串长度的,不过code会看起来零碎很多,用起来感觉也不是很友好,贴个解码的示例code 如下,编码类同。(ms现在都baidu不到示例code的)

//!< encode test  
int src_str_size = 60;   
unsigned char *src_str = (unsigned char *)malloc(src_str_size);  
memset(src_str, '1', src_str_size);  
unsigned char *encode_str = (unsigned char *)malloc( (src_str_size - 1) / 3 * 4 + 4);   
int encode_str_size = EVP_EncodeBlock(encode_str, src_str, src_str_size);  
printf("encode_str_size=%d encode_str:'%s'/n", encode_str_size, encode_str);  
//!< decode test  
EVP_ENCODE_CTX ctx;  
EVP_DecodeInit(&ctx);  
unsigned char *decode_str = (unsigned char *)malloc(src_str_size);  
int decode_str_size = 0;  
int len = 20;   //!< 每次decode 的字节数    
int decode_len = 0;  
int offset = 0;  
while(1)  
{     
    if(offset + len > encode_str_size)  
    {     
        len = encode_str_size - offset;  
    }     
  
    int ret = EVP_DecodeUpdate(&ctx, decode_str + decode_str_size, &decode_len,   
                                  encode_str + offset, len);  
    if(ret == 0) break;  
    if(ret == -1)  
    {  
        printf("error.../n");  
        break;  
    }  
    offset += len;  
    decode_str_size += decode_len;  
}  
EVP_DecodeFinal(&ctx, decode_str, &decode_len);  
decode_str_size += decode_len;  
printf("decode_str:'%s' decode_str_len=%d/n",  
        decode_str, decode_str_size);  

其中EVP_DecodeUpdate 函数,尾部的len参数不可太长(ms最大65),否则会出错
   
----------------
  openssl 库应用甚少,了解也是皮毛,欢迎大家指正

【OpenSSL】OpenSSL实现Base64 Base64就是将二进制数据转换为字符串的一种算法。 阅读详情

相关推荐

通过OpenSSL解码X509证书文件

通过OpenSSL解码X509证书文件,包括*.cer/*.p7b/*.pfx格式文件。

密码开发者 2万+

OpenSSL中提供的base64编解码函数

(本文内容针对 1.0.1c 版本的OpenSSL)         对于 base64 编码,OpenSSL在 evp.h 中声明了相关函数,在 encode.c 中给出了实现。有两种方法: 1. 调用 EVP_EncodeBlock() 函数;用这种方法生成的编码需要解码时,应该调用 EVP_DecodeBlock()。 2. 依次调用 EVP_EncodeInit(), EVP_Enc

henter的专栏 7631

C语言base64编码解码(基于openssl)

#include <openssl/err.h> #include <openssl/ssl.h> #include <openssl/bio.h> #include <openssl/crypto.h> int base64_encode_by_openssl(char *in_str, int in_len, char *out_s...

1397

OpenSSL 使用 base64 编码/解码

介绍有关 OpenSSL 使用 base64 编码/解码。

青春不老,奋斗不止! 1万+

openssl研发之base64编解码实例

Base64编码是一种将二进制数据转换成ASCII字符的编码方式。它主要用于在文本协议中传输二进制数据,例如电子邮件的附件、XML文档、JSON数据等。Base64编码使用64个字符来表示二进制数据,通常使用字母(A-Z、a-z)、数字(0-9)和两个特殊字符(+ 和 /)。有时候,根据具体需求,可能会使用不同的字符集,比如URL安全的Base64编码会使用字符集,其中 “-” 和 “_” 替代了 “+” 和 “/”。Base64编码通常会导致编码后的数据长度略微增加。

N阶二进制的博客 2005

openssl (base64编解码)C++

base64编码,使用c++的编解码的时候一定要注意/0的操作。outlen:bas64解码以后的字符长度。输出的字符中可能存在0,因此可能会造成拿到的字符串长度不正确。返回: char* 需要使用free进行释放,防止内存泄露。返回: char* 为编码结果,需要使用free进行释放。with_new_line:是否换行,64位长度换行。length : base64编码字符串的长度。length:将要编码的字符串长度。input:base64编码字符串。intput:将要编码的字符串。

啊渊的专栏 2306

使用 openssl 进行 base64 编解码

使用 openssl 进行 base64 编解码 BASE64编码介绍 BASE64编码是一种常用的将十六进制数据转换为可见字符的编码。与ASCII码相比,它占用的空间较小。 BASE64编解码原理 将数据编码成BASE64编码时,以3字节数据为一组,转换为24bit的二进制数,将24bit的二进制数分成四组,每组6bit。对于每一组,得到一个数字:0-63。然后根据这个数字查表即得到结果。表如下: 比如有数据:0x30 0x82 0x02 编码过程如下: ...

QCZL_CC的博客 1万+

Base64编码解码

Base64 是一种常用的编码方式,用于将二进制数据转换为可打印的 ASCII 字符串。它的主要特点如下:1. 字符集:Base64 使用了 64 个字符来表示数据,包括大小写字母(A-Z, a-z)、数字(0-9)以及两个特殊字符(+ 和 /)。2. 填充字符:Base64 编码后的字符串长度通常不会与原始数据长度完全对齐。为了保持长度整齐,Base64 在末尾添加一个或两个 `=` 号作为填充字符。3. 编码方式:Base64 编码将每 3 个字节作为一组,转换为 4 个 Base64 字符。

新时代农民工 5800

base64编解码(openssl和c语言2种实现方式)

base64编解码(openssl和c语言2种实现方式)

hfwyydy的博客 1451

智能车八邻域图像算法

智能车八邻域图像算法

技术缝合怪的博客 4万+

sophgo sdk v23.03.01

C/C++程序建议在x86主机上使用交叉编译工具链编译生成可执行文件后,再拷贝到SoC目标平台运行。# 创建docker用户组,若已有docker组会报错,没关系可忽略。对于SoC模式,模型转换也需要在docker开发容器中完成;docker开发容器的配置参照前述章节相关内容。6、创建docker容器并进入Docker。# docker命令免root权限执行。# 将当前用户加入docker组。# 重启docker服务。# 安装 docker。3、安装docker。7、SoC 环境配置。

weixin_40723768的博客 915

通过OpenSSL的接口实现Base64编解码

对openssl genrsa产生的rsa私钥pem文件,使用普通的base64解码会有问题,如使用https://blog.youkuaiyun.com/fengbingchun/article/details/85218653 中介绍的方法,一是有可能不能从返回的结果中直接使用strlen来获得最终字符的大小,因为返回的结果中可能会有0x00;二是pem文件中会有换行符,每行的字节长度超过64个字节就会有换行,普通的base64解码中不会对换行符有处理。在OpenSSL中,默认情况下,base64行长度限制为64个

网络资源是无限的 5678

保姆级避坑指南:在Ubuntu 22.04上成功复现VMamba模型(附完整环境依赖清单)

本文提供了在Ubuntu 22.04上复现VMamba模型的详细指南,包括环境准备、CUDA与PyTorch的精确匹配、依赖安装的疑难杂症解决以及完整环境清单。特别针对Linux系统下的环境复现问题,提供了实用的避坑技巧和验证方法,帮助开发者高效完成VMamba模型的部署。

weixin_29083373的博客 263

用OpenSSL 做Base64 编解码(C++)

参考: http://www.ioncannon.net/programming/34/howto-base64-encode-with-cc-and-openssl/ http://www.ioncannon.net/programming/122/howto-base64-decode-with-cc-and-openssl/ 注意: 1)原文Encode示例代码中有一

yasi_xi的专栏 2万+

【系统移植】 移植主线U-Boot(v2024.01-rc3)到RK3399

[系统移植] 移植主线U-Boot(v2024.01-rc3)到RK3399

Systemcall名屋 1004

嵌入式软考必备知识点:嵌入式系统开发中的重要概念和示例代码

在嵌入式软考中,有一些重要的知识点需要掌握,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口等。实时操作系统是一种专门设计用于嵌入式系统的操作系统,可以提供对任务调度、中断处理和资源管理等方面的支持。GPIO(通用输入输出):GPIO是嵌入式系统中常用的硬件接口,用于连接外部设备和嵌入式系统。以上是嵌入式软考中的一些必备知识点,包括嵌入式系统的基本概念、编程语言、实时操作系统和硬件接口。通过配置串口的波特率、数据位数和校验位等参数,可以实现与其他设备的可靠通信。一、嵌入式系统的基本概念。

PixeGO的博客 314

基于openssl的base64编解码

基于openssl的base64编解码base64原理基于openssl的base64编码基于openssl的base64解码 base64原理 base64是一种编码,并不是一种加密方式。一串base64编码的数据被任何人得到都可以进行解码。 base64编码原理建议参考:base64编码原理 基于openssl的base64编码 size_t BcBase64Encode(const void* data, int data_len, string& res) { BIO* b64 =

qq_41883523的博客 379

MicroChip的SmartFusion2的M2S090芯片的全流程开发环境搭建和Demo设计

MicroChip的SmartFusion2的M2S090芯片的全流程开发环境搭建和Demo设计

qq_45806640的博客 458

OPENSSL Base64编码和解码

 BOOL Base64Encode(unsigned char *pData, int nLeng, int linebreaks, char * pOutBufffer, int *pBufferLenth){    int res = FALSE;    BIO *bmem, *b64;    BUF_MEM *bptr;     b64 = BIO_new(BI

crazy Crypto 3261

用 Message Monitoring Overview 打造接口健康驾驶舱:SAP AIF 消息监控实战解析

究竟解决了什么痛点?概括起来,这个应用把SAP AIF的接口监控,从传统的事务码和技术视角,带到了一个更加直观、业务友好的层次:(通过卡片式总览,让你在一个页面上看到所有自己负责的接口及其健康状况。通过和的联动,实现了从接口态势到具体消息的快速钻取。通过Recipient模型和应用,实现了监控职责的灵活分配。借助拖拽排序、搜索过滤等特性,让每个运维人员都可以打造属于自己的接口健康 cockpit。如果你正在做S/4HANA或项目,无论是公有云还是本地部署,只要系统启用了SAP AIF。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 107

笔试题-2023-芯原-数字前端设计or验证【纯净题目版】

笔试题-2023-芯原-数字前端设计or验证【纯净题目版】

w0shishabi的博客 5685

利用openssl进行base64的编码与解码

openssl可以直接使用命令对文件件进行base64的编码与解码,利用openssl提供的API同样可以做到这一点。 废话不多说,直接上代码了。需要注意的是通过base64编码后的字符每64个字节都会有一个换行符的存在。 static int base64_encode(char *str,int str_len,char *encode,int encode_len){ BIO

求索 1836

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

如何利用openssl来进行base64编解码?

openssl的用法, 请见之前博文, 下面仅仅给出base64编解码的代码: #include #include #pragma comment(lib, "libeay32.lib") #pragma comment(lib, "ssleay32.lib") // 可以注释掉 using namespace std; // base64编码 int Base64Encode(con

认知 行动 坚持 1万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

openssl中的base64

base64是一种基于64个可打印字符来表示二进制数据的方法。核心的方法是38 = 64;该怎么理解这个3 * 8 = 6 *4 呢?一个字节占8位,以3个字节为一组,将其24位拆成4个字节,每个字节填充6位,之后在6位的前面补两个0,形成4个字节形式。当然如果原文不够3个字节怎么办呢?加入还剩一个数,则将该数继续原来的操作,会转换成2个字节,然后不够四个字节,就在剩余的两个字节用’='进行补全。...

m0_38126105的博客 2439

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

上一篇: opendir 、readdir 小结
下一篇: strcasecmp函数用法
cofftech
博客等级 码龄16年 46粉丝 76原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值