当前位置: 首页 > 编程日记 > 正文

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

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

先介绍下使用命令行openssl base64进行编解码:

(1).对” https://blog.csdn.net/fengbingchun”进行编解码,执行命令及结果如下:

(2).对长串进行编解码,如” https://blog.csdn.net/fengbingchun https://github.com//fengbingchun”,执行命令及结果如下:编码长度超过64个字符长度,会进行换行,若不想换行,可增加使用”-A”选项

(3).对指定文件进行编解码:如文件1.txt,先进行编码生成2.txt,然后再对2.txt进行解码生成3.txt,执行命令及结果如下:

下面是通过调用openssl的相关接口组合成的base64编解码实现:由外部负责申请足够的空间用于存放结果,最后一个参数用于指明编解码中是否换行。

int openssl_base64_encode(const unsigned char* in, int inlen, char* out, int* outlen, bool newline)
{BIO* b64 = BIO_new(BIO_f_base64());BIO* bmem = BIO_new(BIO_s_mem());if (!b64 || !bmem) {fprintf(stderr, "fail to BIO_new\n");return -1;}b64 = BIO_push(b64, bmem);if (!newline)BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // ignore newlines, write everything in one line*outlen = BIO_write(b64, in, inlen);if (*outlen <= 0 || *outlen != inlen) {fprintf(stderr, "fail to BIO_write\n");return -1;}BIO_flush(b64);BUF_MEM* buf = nullptr;BIO_get_mem_ptr(b64, &buf);*outlen = buf->length;memcpy(out, buf->data, *outlen);BIO_free_all(b64);return 0;
}int openssl_base64_decode(const char* in, int inlen, unsigned char* out, int* outlen, bool newline)
{BIO* b64 = BIO_new(BIO_f_base64());BIO* bmem = BIO_new_mem_buf(in, inlen);if (!b64 || !bmem) {fprintf(stderr, "fail to BIO_new\n");return -1;}b64 = BIO_push(b64, bmem);if (!newline)BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // ignore newlines, write everything in one line*outlen = BIO_read(b64, out, inlen);if (*outlen <= 0) {fprintf(stderr, "fail to BIO_read\n");return -1;}BIO_free_all(b64);return 0;
}

下面是通过编解码字符串的测试代码:

int test_openssl_base64_simple()
{const char* src = "https://blog.csdn.net/fengbingchun https://github.com//fengbingchun";int inlen = strlen(src);int outlen = (inlen + 2) / 3 * 4 + ((inlen + 2) / 3 * 4 + 63) / 64;std::unique_ptr<char[]> out1(new char[outlen]);bool newline = true;int ret = openssl_base64_encode((const unsigned char*)src, inlen, out1.get(), &outlen, newline);if (ret != 0) {fprintf(stderr, "fail to openssl_base64_encode\n");return -1;}fprintf(stdout, "encode result:\n");std::for_each(out1.get(), out1.get() + outlen, [](char& c) { fprintf(stdout, "%c", c); });fprintf(stdout, "\n");std::unique_ptr<unsigned char[]> dst(new unsigned char[outlen]);int outlen1 = 0;ret = openssl_base64_decode(out1.get(), outlen, dst.get(), &outlen1, newline);if (ret != 0) {fprintf(stderr, "fail to openssl_base64_decode\n");return -1;}fprintf(stdout, "decode result:\n");std::for_each(dst.get(), dst.get() + outlen1, [](unsigned char& c) { fprintf(stdout, "%c", (char)c); });fprintf(stdout, "\n");dst[outlen1] = '\0';if (strcmp(src, (const char*)dst.get()) == 0) {fprintf(stdout, "test success\n");return 0;} else {fprintf(stdout, "test fail\n");return -1;}
}

执行结果如下图所示:

之前在https://blog.csdn.net/fengbingchun/article/details/106546012中使用OpenSSL的函数PEM_read_RSAPrivateKey直接对pem文件进行解析,下面测试代码是通过调用上面的base64解码函数实现的解析:

int test_openssl_base64_complex()
{
#ifdef _MSC_VERconst char* name = "E:/GitCode/OpenSSL_Test/testdata/rsa_private.pem";
#elseconst char* name = "testdata/rsa_private.pem";
#endifconst char* begin = "-----BEGIN RSA PRIVATE KEY-----";const char* end = "-----END RSA PRIVATE KEY-----";FILE *fp = fopen(name, "rb");if (!fp) {fprintf(stderr, "fail to open file: %s\n", name);return -1;}fseek(fp, 0, SEEK_END);long length = ftell(fp);rewind(fp);std::unique_ptr<unsigned char[]> data(new unsigned char[length]);fread(data.get(), 1, length, fp);fclose(fp);const char* p1 = strstr((const char*)data.get(), begin);if (!p1) {fprintf(stderr, "it's not a pem file: %s\n", name);return -1;}const char* p2 = strstr((const char*)data.get(), end);if (!p2) {fprintf(stderr, "it's not a pem file: %s\n", name);return -1;}bool newline = true;long length2 = p2 - p1;std::unique_ptr<unsigned char[]> decoded(new unsigned char[length2]);int outlen = 0;int ret = openssl_base64_decode(p1 + strlen(begin) + 1, length2, decoded.get(), &outlen, newline); // + 一个换行符长度const unsigned char* p = decoded.get();RSA_PRIVATE_KEY* key = d2i_RSA_PRIVATE_KEY(nullptr, &p, outlen);if (!key) {fprintf(stderr, "fail to d2i_RSA_PRIVATE_KEY\n");return -1;}print(key->version, "version");print(key->n, "n");print(key->e, "e");print(key->d, "d");print(key->p, "p");print(key->q, "q");print(key->exp1, "exp1");print(key->exp2, "exp2");print(key->coeff, "coeff");RSA_PRIVATE_KEY_free(key);return 0;
}

执行结果如下:与直接使用PEM_read_RSAPrivateKey得到的结果是一致的

以上代码段的完整code见:GitHub/OpenSSL_Test

GitHub:https://github.com/fengbingchun/OpenSSL_Test

相关文章:

激辩:机器究竟能否理解常识?

【12月公开课预告】&#xff0c;入群直接获取报名地址12月11日晚8点直播主题&#xff1a;人工智能消化道病理辅助诊断平台——从方法到落地12月12日晚8点直播&#xff1a;利用容器技术打造AI公司技术中台12月17日晚8点直播主题&#xff1a;可重构计算&#xff1a;能效比、通用性…

Mac OS X 下Node.js开发环境的搭建

1.安装Xcode2.安装Homebrew 谷歌搜索Homebrew 复制命令行 打开终端 粘贴命令行 点击回车 安装 输入密码等2.安装Nodejs利用Homebrew安装nodejs打开终端 输入 &#xff1a;brew install nodejs 回车查询nodejs版本&#xff1a;node --version3.安装文档数据库 MongoDB打开终…

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

.NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码&#xff0c;例如以下所看到的&#xff1a; /// <summary>/// MySql 数据库操作类/// </summary>public class MySqlHelper{/// <summary>/// MysqlConnection/// </summ…

Instagram个性化推荐工程中三个关键技术是什么?

作者 | Ivan Medvedev&#xff0c;Haotian Wu&#xff0c;Taylor Gordon译者 | 陆离编辑 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; 【导语】近期&#xff0c;Facebook 在博客上分享了第一篇详细介绍 Explore 系统关键技术&#xff0c;以及 I…

iOS UIbutton 点击无反应的几种情况

1、UIButton不能点击情况的第一种是&#xff0c;你将button添加到一个不能响应点击事件的View里。如你将button添加到UIImageView中&#xff0c;解决办法只需将UIImageView的 userInteractionEnabled设为YES即可。 例如&#xff1a; self.headImgV [[UIImageView alloc] ini…

C和C++安全编码笔记:格式化输出

C标准中定义了一些可以接受可变数量参数的格式化输出参数&#xff0c;参数中包括一个格式字符串。printf()和sprintf()都是格式化输出函数的例子。格式化输出函数是由一个格式字符串和可变数目的参数构成的。在效果上&#xff0c;格式化字符串提供了一组可以由格式化输出函数解…

谈谈UI架构设计的演化

谈谈UI架构设计的演化 经典MVC 在1979年&#xff0c;经典MVC模式被提出。 在当时&#xff0c;人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来&#xff0c;而Trygve Reenskaug在跟一些人的讨论中&#xff0c;逐渐剥离出一系列的概念&#xff0c;最初是T…

JWT(JSON Web Token)简介及实现

JWT(JSON Web Token)&#xff1a;是一个开放标准(RFC 7519)&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用于在各方之间作为Json对象安全地传输信息。由于此信息是经过数字签名的&#xff0c;因此可以被验证和信任。可以使用HMAC SHA256或RSA等对JWT进行签名。 JW…

iOS UIImageView 加载含有汉字的url处理方法

NSString *url [model.pic stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; [self.headImgView sd_setImageWithURL:[NSURL URLWithString:url]];

《评人工智能如何走向新阶段》后记

由AI科技大本营下载自视觉中国自《评人工智能如何走向新阶段》一文发表&#xff08;在内部&#xff09;后&#xff0c;引来了中外专家、草根们的广泛议论&#xff0c;有深有浅&#xff0c;其中似有一些思考价值&#xff0c;故录入本文后记&#xff1a; 中外专家、草根们23条议…

用XCA(X Certificate and key management)可视化程序管理SSL 证书(3)--创建自己定义的凭证管理中心(Certificate Authority)...

在第“用XCA&#xff08;X Certificate and key management&#xff09;可视化程序管理SSL 证书&#xff08;2&#xff09;---创建证书请求”章节中&#xff0c;我们介绍了怎样用XCA创建SSL证书请求&#xff08;Certificate Request&#xff09;&#xff0c;在一章节中&#xf…

C和C++安全编码笔记:并发

并发是一种系统属性&#xff0c;它是指系统中几个计算同时执行&#xff0c;并可能彼此交互。一个并发程序通常使用顺序线程和(或)进程的一些组合来执行计算&#xff0c;其中每个线程和进程执行可以在逻辑上并行执行的计算。这些进程和(或)线程可以在单处理器系统上使用分时抢占…

《评人工智能如何走向新阶段》后记(再续1)

由AI科技大本营下载自视觉中国中外专家、草根对《评人工智能如何走向新阶段》一文进行广泛议论&#xff0c;已在《后记》中发表原创&#xff08;未加修改&#xff09;的23条议论&#xff0c;现再续发24-30条如下&#xff1a; 24.最近半年来&#xff0c;人工智能的发展重心逐渐…

iOS UITextView 随键盘弹出界面上移

- (void)textViewDidBeginEditing:(UITextView *)textView { CGRect frame textView.frame; int offSet frame.origin.y 70 - (self.view.frame.size.height - 216.0); //iphone键盘高度为216.iped键盘高度为352 [UIView beginAnimations:"ResizeForKeyboard" co…

H3C 交换机命名规则

例&#xff1a;H3C-S5500-28C-EIH3C&#xff1a;为固定值&#xff0c;就是“H3C”这个品牌S的位置&#xff1a;代表产品系列『S 代表交换机SR 代表业务路由器』第一个5的位置:代表产品子系列号『3系为千兆上行,百兆下行的合适交换机 例:S3600 S31005系为全千兆的盒式交换机 …

iOS 时间选择器封装(含三种模式)

#import <UIKit/UIKit.h> typedef enum : NSUInteger { DatePickerViewDateTimeMode,//年月日,时分 DatePickerViewDateMode,//年月日 DatePickerViewTimeMode//时分 } DatePickerViewMode; protocol DateTimePickerViewDelegate <NSObject> optional /** * 确定按…

C和C++安全编码笔记:总结

《C和C安全编码》(原书第2版)这本书是2013年出版的。 这里是基于之前所有笔记的简单总结&#xff0c;笔记列表如下&#xff1a; 字符串&#xff1a;https://blog.csdn.net/fengbingchun/article/details/105325508 指针诡计&#xff1a;https://blog.csdn.net/fengbingchun/…

《评人工智能如何走向新阶段》后记(再续2)

由AI科技大本营下载自视觉中国从朋友那里获知&#xff0c;有一块供大家自由议论人工智能的园地&#xff08;内部的&#xff09;&#xff0c;我通过有关关系进入后&#xff0c;一览之余&#xff0c;果然生动活泼&#xff0c;没有学究气&#xff0c;从已发表的30条议论来看。有原…

Dokku和Docker的完美配合

看到一篇不错的文章&#xff0c;收藏一下&#xff1a; 【编者的话】本文作者介绍了如何在单机上将Dokku和Docker结合。Dokku是一个小型的PaaS平台&#xff0c;只需使用Git将代码push到对应的仓库上就能自动触发部署&#xff0c;构建过程非常简单。但是Dokku对于用户来说&#x…

iOS封装分页效果

#import <UIKit/UIKit.h> interface WPageTitleView : UIView property (nonatomic,assign) NSInteger selectedIndex; //添加参数数组 property (nonatomic,strong) NSArray *titles; property (nonatomic,copy) void (^buttonSelected)(NSInteger index); end #impo…

Windows/Linux TCP Socket网络编程简介及测试代码

典型的网络应用是由一对程序(即客户程序和服务器程序)组成的&#xff0c;它们位于两个不同的端系统中。当运行这两个程序时&#xff0c;创建了一个客户进程和一个服务器进程&#xff0c;同时它们通过从套接字(socket)读出和写入数据在彼此之间进行通信。开发者创建一个网络应用…

《评人工智能如何走向新阶段》后记(再续3)

由AI科技大本营下载自视觉中国35.阿里巴巴旗下芯片公司平头哥在乌镇互联网大会上宣布开源低功耗微控制芯片&#xff08;MCU&#xff09;设计平台&#xff0c;这一平台面向 AIoT 时代的定制化芯片设计需求&#xff0c;目标群体包括芯片设计公司、IP 供应商、高校及科研院所等&am…

ffmpeg 基本用法大全

FFmpegFFmpeg 基本用法本课要解决的问题1.FFmpeg的转码流程是什么&#xff1f;2.常见的视频格式包含哪些内容吗&#xff1f;3.如何把这些内容从视频文件中抽取出来&#xff1f;4.如何从一种格式转换为另一种格式&#xff1f;5.如何放大和缩小视频&#xff1f;6.如何旋转&#x…

快过年了,为过完年跳槽的人准备一份面试题

设计模式是什么&#xff1f; 你知道哪些设计模式&#xff0c;并简要叙述&#xff1f; 设计模式是一种编码经验&#xff0c;就是用比较成熟的逻辑去处理某一种类型的事情。 1). MVC模式&#xff1a;Model View Control&#xff0c;把模型 视图 控制器 层进行解耦合编写。 2). MV…

Ubuntu上Vim安装NERDTree插件操作步骤

NERDTree是Vim的文件系统浏览器&#xff0c;使用此插件&#xff0c;用户可以直观地浏览复杂的目录层次结构&#xff0c;快速打开文件以进行读取或编辑&#xff0c;以及执行基本的文件系统操作。NERDTree源码在https://github.com/preservim/nerdtree。 这里通过Vundle安装NERD…

《评人工智能如何走向新阶段》后记(再续4)

由AI科技大本营下载自视觉中国41. 在人工智能感知阶段&#xff0c;依靠数据驱动的深度学习算法。目前5种最流行的深度学习架构: ① 递归神经网络&#xff08;RNN&#xff09;② 长短期记忆 &#xff08;LSTM&#xff09;/门控递归单元&#xff08;GRU&#xff09;③卷积神经网络…

电视游戏会是未来客厅娱乐的主角吗?

在时下流行的多屏生态概念中&#xff0c;电视虽为最大屏幕&#xff0c;但与智能手机、平板等小屏相比&#xff0c;属于相对较弱的一环。无移动性、自身交互性不足&#xff0c;在一定程度上影响着它在移动时代的发展。而作为最能体现其“吸睛能力”的——大屏娱乐功能&#xff0…

王爽著的《汇编语言》第3版笔记

王爽著的《汇编语言》(第3版)于2013年出版&#xff0c;虽然是2013年出版的&#xff0c;但书中部分内容感觉已过时&#xff1a; (1). 基于intel 8086 CPU介绍&#xff0c;intel 8086是英特尔公司上个世纪生产的芯片&#xff0c;是16位的&#xff0c;早已停产&#xff1b; (2).…

iOS 倒计时方法

//启动计时器 double delayInSeconds 10.0; dispatch_time_t popTime dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ //执行事件 NSLog("计时器结束了"); UIAlertController …

《评人工智能如何走向新阶段》后记(再续5)

由AI科技大本营下载自视觉中国51.今年发表的由俄罗斯“脑机接口”公司&#xff08;Neurobotics&#xff09;和莫斯科物理技术学院&#xff08;MIPT&#xff09;研究的一种全新“脑机接口”算法。利用“脑机接口”将人脑&#xff08;EEG&#xff09;神经元与脑外深度学习网络连接…