OpenSSL RSA加密和解密

2023-11-13

rsa加密的密钥格式常见的有两种:
一种是PKCS#1,密钥头为

-----BEGIN RSA PUBLIC KEY-----

一种是PKCS#8,密钥头为

-----BEGIN PUBLIC KEY-----

以字符串公钥为例,对PKCS#1格式的密钥加载使用的函数是PEM_read_bio_RSAPublicKey(),而对PKCS#8格式公钥的加载使用的是函数PEM_read_bio_RSA_PUBKEY()。
 

1、生成密钥对

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#ifndef _WIN64
#pragma comment(lib, "libcrypto.lib")
#else
#pragma comment(lib, "libcrypto-x64.lib")
#endif // WIN32

#define KEY_LENGTH  1024             // 密钥长度  
#define PUB_KEY_FILE "pubkey.pem"    // 公钥路径  
#define PRI_KEY_FILE "prikey.pem"    // 私钥路径  

// 随机生成密钥字符串
BOOL generateRSAKey()
{
	// 公私密钥对    
	size_t pri_len;
	size_t pub_len;
	char *ucPriKey = NULL;
	char *ucPubKey = NULL;

	// 生成密钥对    
	RSA *keypair = RSA_generate_key(KEY_LENGTH, RSA_F4, NULL, NULL);

	BIO *pri = BIO_new(BIO_s_mem());
	BIO *pub = BIO_new(BIO_s_mem());

	PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
	PEM_write_bio_RSAPublicKey(pub, keypair);

	// 获取长度    
	pri_len = BIO_pending(pri);
	pub_len = BIO_pending(pub);

	// 密钥对读取到字符串
	ucPriKey = (char *)malloc(pri_len + 1);
	ucPubKey = (char *)malloc(pub_len + 1);

	BIO_read(pri, ucPriKey, pri_len);
	BIO_read(pub, ucPubKey, pub_len);

	ucPriKey[pri_len] = '\0';
	ucPubKey[pub_len] = '\0';

	// 存储密钥对    
	FILE *pubFile = fopen(PUB_KEY_FILE, "w");
	if (pubFile == NULL)
		return FALSE;

	fputs(ucPubKey, pubFile);
	fclose(pubFile);

	FILE *priFile = fopen(PRI_KEY_FILE, "w");
	if (priFile == NULL)
		return FALSE;

	fputs(ucPriKey , priFile);
	fclose(priFile);

	// 内存释放  
	RSA_free(keypair);
	BIO_free_all(pub);
	BIO_free_all(pri);

	free(ucPriKey);
	free(ucPubKey);
	return TRUE;
}

// 根据密钥字符串生成密钥对
RSA * createRSA(unsigned char * ucKey, bool IsPubkey)
{
	RSA *rsa = NULL;
	BIO *keybio;

	keybio = BIO_new_mem_buf(ucKey, -1);
	if (keybio == NULL)
	{
		printf("Failed to create key BIO");
		return 0;
	}

	if (IsPubkey)
	{
		rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);
	}
	else
	{
		rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
	}
	
	if (rsa == NULL)
	{
		printf("Failed to create RSA");
	}

	return rsa;
}

2、公钥加密 -> 私钥解密

int public_encrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPubKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPubKey, 1);
	int  result = RSA_public_encrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

int private_decrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPriKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPriKey, 0);
	int  result = RSA_private_decrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

3、私钥加密 -> 公钥解密

int private_encrypt(unsigned char * ucKey, int nKeyLen, unsigned char * ucPriKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPriKey, 0);
	int result = RSA_private_encrypt(nKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

int public_decrypt(unsigned char * ucKey, int ulKeyLen, unsigned char * ucPubKey, unsigned char *outData)
{
	RSA * rsa = createRSA(ucPubKey, 1);
	int  result = RSA_public_decrypt(ulKeyLen, ucKey, outData, rsa, RSA_PKCS1_PADDING);
	if (rsa != NULL)
	{
		RSA_free(rsa);
		rsa = NULL;
	}

	return result;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenSSL RSA加密和解密 的相关文章

随机推荐

  • centos7 安装 bugfree3

    1 安装apache yum install httpd 2 安装mysql wget i c http dev mysql com get mysql57 community release el7 10 noarch rpm yum y
  • set的特点

    set不允许元素重复且无序 常用实现有HashSet LinkedHashSet和TreeSet HashSet通过HashMap实现 HashMap的key即HashSet存储的元素 所有key都使用相同的Value 一个名为PRESNT
  • 6. Modules

    6 Modules 如果你退出 Python 解释器并重新进入 你做的任何定义 变量和方法 都会丢失 因此 如果你想要编写一些更大的程序 最好使用文本编辑器先编写好 然后运行这个文件 这就是所谓的创建 脚本 随着你的程序变得越来越长 你可能
  • C语言--学生管理系统--(完整代码)

    本系统分成了三个文件 main c student c student h 功能 实现对班级成员的增加 删除 修改 遍历 根据成绩排序 增加 会检查 现在班级已有的人数 班级是否已满 没有学号重复检测 删除 根据学号查询 gt 删除 会判断
  • 【Java开发环境配置】1-JDK安装教程&环境变量配置(21)

    一 JDK概念 JDK 是Java开发工具包 Java Development Kit 的缩写 它是一种用于构建在 Java 平台上发布的应用程序 applet 和组件的开发环境 其中包括了Java编译器 JVM 大量的Java工具以及Ja
  • stata豪斯曼检验报错

    xsmle gdp gt cz gdzc ersan ur model sdm wmat Wzhusj hausman nolog Warning All regressors will be spatially lagged 在使用xsm
  • 转载:switch/case语句中,每个case都要加花括号

    前言 多写代码 才能发现问题 即使现成的代码 手打一遍也有收获 这不遇到一个很无语的问题 问题及原因 解决方法见以下转载内容 原创者 ChirlChen 博客地址 https blog csdn net qqmindyourwill art
  • 网络编程之网络丢包故障如何定位?如何解决?

    引言 本期分享一个比较常见的网络问题 丢包 例如我们去ping一个网站 如果能ping通 且网站返回信息全面 则说明与网站服务器的通信是畅通的 如果ping不通 或者网站返回的信息不全等 则很可能是数据被丢包了 类似情况想必大家都不陌生 针
  • 3分钟搞懂:JavaScript 和 ECMAScript

    JavaScript 和 ECMAScript ECMAScript 是 JavaScript 语言的国际标准 JavaScript 是 ECMAScript 的一种实现 Adobe ActionScript 和 JScript 同样实现了
  • 基于Bochs安装GeekOs

    开发环境介绍 1 Ubuntu 16 04 2 boch2 6 11 下载地址 http sourceforge net projects bochs files bochs 2 6 11 3 nasm 2 08 01 下载地址 http
  • CommonJS,ES6 Module以及webpack模块打包原理

    CommonJS ES6 Module以及webpack模块打包原理 模块化历程 CommonJS 模块 导出 导入 ES6 Module 模块 导出 命名导出 默认导出 导入 导入命名导出的模块 导入默认导出的模块 CommonJS 与
  • 夯实C++基础:1.C++生命周期和编程范式、预处理、编译相关

    一直告诉自己要保持学习 但真的工作之后 反而不知道从哪里开始学起 就这么拖着光有想法没有行动 除了加班没有那么晚刷刷题之外 就从看课有人带着学开始夯实基础吧 反正学啥都比不学好 之后可以看设计模式 网络编程 STL深入学一学 也可以看书ef
  • MySQL的安装教程

    MySQL的安装教程 今天来唠一唠MySQL的事 首先是mysql的一些知识点 接下来我们先说MySQL的安装教程 1 安装程序安装 首先 去数据库的官网http www mysql com下载MySQL 一般为 msi文件 下载好之后双击
  • Matlab:从csv文件中读取某一列的数据

    第一种 M CSVREAD FILENAME 直接读取csv文件的数据 并返回给M 第二种 M CSVREAD FILENAME R C 读取csv文件中从第R 1行 第C 1列的数据开始的数据 这对带有头文件说明的csv文件 如示波器等采
  • 华为OD面经(给了口头offer祈祷流程审批能过ε=(´ο`*)))唉)

    1 上来一到算法题相对简单 2 介绍一下自己的项目 问了java的jvm相关如jvm在遇到线程挂掉时的日志操作啥的有做过吗 spring的好处原理 springboot的好处原理 微服务的锁 日志相关 垃圾回收算法 redis的原理 has
  • c#+npgsql采坑记录

    c npgsql 数据库作业采坑记录 做数据库作业时踩了些坑 做个记录 1 pgsql的主键int的模糊查询 pgsql中以int作为主键 比如student以sid作为主键 当sid为int时 模糊查询会使索引失效 而mysql没有这个问
  • Vue的大坑 input手动赋值后无法修改问题

    当获取数据之后 手动赋值给input 会出现渲染成功 能读取数据 但是无法修改情况 代码如下 根据ID查询返回订单信息 async editOrdersAddress orderId const data res await this ht
  • 力学应用计算机实例,PART 5 相图计算机计算 相图计算与 及扩散动力学模拟及其应用实例.ppt...

    PART 5 相图计算机计算 相图计算与 及扩散动力学模拟及其应用实例 ppt 亚点阵模型假设 每一亚点阵内的原子只与其他亚点阵内的原子相邻 这一点可以通过亚点阵的选取来保证 最近邻相互作用是常数 各亚点阵之间的相互作用忽略不计 过剩自由能
  • 前端开发模式的迭代

    前端开发模式的迭代 前端开发给人的印象一直是变化太快 不断出现新的框架 库 开发模式 这些开发模式有什么不同 为什么要不断迭代 本文将分享几种常见的前端开发模式 讲解前端开发模式的演变过程 传统开发模式 前端是 Web 应用的组成部分 前端
  • OpenSSL RSA加密和解密

    rsa加密的密钥格式常见的有两种 一种是PKCS 1 密钥头为 BEGIN RSA PUBLIC KEY 一种是PKCS 8 密钥头为 BEGIN PUBLIC KEY 以字符串公钥为例 对PKCS 1格式的密钥加载使用的函数是PEM re