20.2 OpenSSL 非对称RSA加解密算法

RSA算法是一种非对称加密算法,由三位数学家RivestShamirAdleman共同发明,以他们三人的名字首字母命名。RSA算法的安全性基于大数分解问题,即对于一个非常大的合数,将其分解为两个质数的乘积是非常困难的。

RSA算法是一种常用的非对称加密算法,与对称加密算法不同,RSA算法使用一对非对称密钥,分别为公钥和私钥,公钥和私钥是成对生成的,公钥可以公开,用于加密数据和验证数字签名,而私钥必须保密,用于解密数据和生成数字签名。因此,RSA算法的使用场景是公钥加密、私钥解密,或者私钥加密、公钥解密。

OpenSSL库中提供了针对此类算法的支持,但在使用时读者需要自行生成公钥与私钥文件,在开发工具包内有一个openssl.exe程序,该程序则是用于生成密钥对的工具,当我们需要使用非对称加密算法时,则可以使用如下命令生成公钥和私钥。

  • 生成私钥: openssl genrsa -out rsa_private_key.pem 1024
  • 生成公钥: openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

读者执行上述两条命令后即可得到rsa_private_key.pem私钥,以及rsa_public_key.pem公钥,如下图所示;

在使用非对称加密时,读者需要分别导入所需要的头文件,这其中就包括了rsa.h用于处理加密算法的库,以及pem.h用于处理私钥的库,这两个库是使用RSA时必须要导入的。

#include <iostream>
#include <string>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/crypto.h>extern "C"
{
#include <openssl/applink.c>
}#pragma comment(lib,"libssl.lib")
#pragma comment(lib,"libcrypto.lib")

20.2.1 公钥加密私钥解密

RSA公钥用于加密数据和验证数字签名,私钥用于解密数据和生成数字签名,通常用于公钥加密、私钥解密的场景,具有较高的安全性,但加密和解密速度较慢,因此通常采用一种混合加密方式,即使用RSA算法加密对称加密算法中的密钥,再使用对称加密算法加密数据,以保证数据的机密性和加密解密的效率。

首先我们来实现公钥加密功能,如下Public_RsaEncrypt函数,该函数接受两个参数,分别是需要加密的字符串以及公钥文件,代码中首先通过fopen()打开一个公钥文件,并通过PEM_read_RSA_PUBKEY函数读入并初始化公钥文件,接着调用RSA_public_encrypt该函数主要用于实现公钥加密,当加密成功后返回加密后的文本内容,类型是字符串。

// 公钥加密
std::string Public_RsaEncrypt(const std::string& str, const std::string& path)
{RSA* rsa = NULL;FILE* file = NULL;char* ciphertext = NULL;int len = 0;int ret = 0;file = fopen(path.c_str(), "r");if (file == NULL){return std::string();}rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL);if (rsa == NULL){ERR_print_errors_fp(stdout);fclose(file);return std::string();}len = RSA_size(rsa);ciphertext = (char*)malloc(len + 1);if (ciphertext == NULL){RSA_free(rsa);fclose(file);return std::string();}memset(ciphertext, 0, len + 1);ret = RSA_public_encrypt(str.length(), (unsigned char*)str.c_str(), (unsigned char*)ciphertext, rsa, RSA_PKCS1_PADDING);if (ret < 0){ERR_print_errors_fp(stdout);free(ciphertext);RSA_free(rsa);fclose(file);return std::string();}std::string s(ciphertext, ret);free(ciphertext);RSA_free(rsa);fclose(file);return s;
}

与公钥加密方法类似,Private_RsaDecrypt函数用于使用私钥进行解密,该函数接受两个参数,第一个参数是加密后的字符串数据,第二个参数则是私钥的具体路径,函数中通过PEM_read_RSAPrivateKey实现对私钥的初始化,并通过RSA_private_decrypt函数来实现对特定字符串的解密操作。

// 私钥解密
std::string Private_RsaDecrypt(const std::string& str, const std::string& path)
{RSA* rsa = NULL;FILE* file = NULL;char* plaintext = NULL;int len = 0;int ret = 0;file = fopen(path.c_str(), "r");if (file == NULL){return std::string();}rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);if (rsa == NULL){ERR_print_errors_fp(stdout);fclose(file);return std::string();}len = RSA_size(rsa);plaintext = (char*)malloc(len + 1);if (plaintext == NULL){RSA_free(rsa);fclose(file);return std::string();}memset(plaintext, 0, len + 1);ret = RSA_private_decrypt(str.length(), (unsigned char*)str.c_str(), (unsigned char*)plaintext, rsa, RSA_PKCS1_PADDING);if (ret < 0){ERR_print_errors_fp(stdout);free(plaintext);RSA_free(rsa);fclose(file);return std::string();}std::string s(plaintext, ret);free(plaintext);RSA_free(rsa);fclose(file);return s;
}

这两段代码的调用也非常容易,如下代码片段则分别实现了对text字符串的加密与解密功能,使用公钥加密,使用私钥解密。

int main(int argc, char* argv[])
{std::string text = "hello lyshark";// 公钥加密std::string public_path = "d://rsa_public_key.pem";std::string encry = Public_RsaEncrypt(text, public_path);// std::cout << "加密后文本: " << encry << std::endl;// 私钥解密std::string private_path = "d://rsa_private_key.pem";std::string decry = Private_RsaDecrypt(encry, private_path);std::cout << "解密后文本: " << decry << std::endl;system("pause");return 0;
}

这段代码输出效果如下图所示;

20.2.2 私钥加密公钥解密

在RSA算法中,私钥加密公钥解密并不是一种常见的使用方式,因为私钥是用于签名而不是加密的。通常的使用方式是,使用公钥加密,私钥解密,这样可以保证数据的机密性,只有拥有私钥的人才能解密数据,但在某些时候我们不得不将这个流程反过来,使用私钥加密并使用公钥解密。

私钥加密的封装代码如下所示,其中Private_RsaEncrypt用于实现私钥加密,该函数同样接受两个参数,分别是待加密字符串以及当前私钥路径,函数的核心部分是RSA_private_encrypt该函数可用于使用私钥对数据进行加密。

// 私钥加密
std::string Private_RsaEncrypt(const std::string& str, const std::string& path)
{RSA* rsa = NULL;FILE* file = NULL;char* ciphertext = NULL;int len = 0;int ret = 0;file = fopen(path.c_str(), "r");if (file == NULL){return std::string();}rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);if (rsa == NULL){ERR_print_errors_fp(stdout);fclose(file);return std::string();}len = RSA_size(rsa);ciphertext = (char*)malloc(len + 1);if (ciphertext == NULL){RSA_free(rsa);fclose(file);return std::string();}memset(ciphertext, 0, len + 1);ret = RSA_private_encrypt(str.length(), (unsigned char*)str.c_str(), (unsigned char*)ciphertext, rsa, RSA_PKCS1_PADDING);if (ret < 0){ERR_print_errors_fp(stdout);free(ciphertext);RSA_free(rsa);fclose(file);return std::string();}std::string s(ciphertext, ret);free(ciphertext);RSA_free(rsa);fclose(file);return s;
}

公钥解密的实现方法与加密完全一致,代码中Public_RsaDecrypt函数用于实现公钥解密,其核心功能的实现依赖于RSA_public_decrypt这个关键函数。

// 公钥解密
std::string Public_RsaDecrypt(const std::string& str, const std::string& path)
{RSA* rsa = NULL;FILE* file = NULL;char* plaintext = NULL;int len = 0;int ret = 0;file = fopen(path.c_str(), "r");if (file == NULL){return std::string();}rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL);if (rsa == NULL){ERR_print_errors_fp(stdout);fclose(file);return std::string();}len = RSA_size(rsa);plaintext = (char*)malloc(len + 1);if (plaintext == NULL){RSA_free(rsa);fclose(file);return std::string();}memset(plaintext, 0, len + 1);ret = RSA_public_decrypt(str.length(), (unsigned char*)str.c_str(), (unsigned char*)plaintext, rsa, RSA_PKCS1_PADDING);if (ret < 0){ERR_print_errors_fp(stdout);free(plaintext);RSA_free(rsa);fclose(file);return std::string();}std::string s(plaintext, ret);free(plaintext);RSA_free(rsa);fclose(file);return s;
}

有了上述方法,那么调用代码则变得很容易,如下所示,我们将text字符串使用私钥进行加密,并使用公钥进行解密。

int main(int argc, char* argv[])
{std::string text = "hello lyshark";// 私钥加密std::string private_path = "d://rsa_private_key.pem";std::string encry = Private_RsaEncrypt(text, private_path);// std::cout << "加密后文本: " << encry << std::endl;// 公钥解密std::string public_path = "d://rsa_public_key.pem";std::string decry = Public_RsaDecrypt(encry, public_path);std::cout << "解密后文本:" << decry << std::endl;system("pause");return 0;
}

这段代码输出效果如下图所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/176378.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内网渗透-域信息收集

域环境 虚拟机应用&#xff1a;vmware17 域控主机&#xff1a;win2008 2r 域成员主机&#xff1a;win2008 2r win7 一.域用户和本地用户区别 使用本地用户安装程序时&#xff0c;可以直接安装 使用域用户安装程序时&#xff0c;需要输入域控管理员的账号密码才能安装。总结…

Leetcode.树形DP

目录 543.二叉树的直径 124.二叉树中的最大路径和 2246.相邻字符不同的最长路径 543.二叉树的直径 用递归来写 考虑 树形DP 维护以当前节点为根节点的最大值&#xff0c;同时返回给父节点经过当前节点的最大链的长度&#xff0c;这有个trick 当遍历到空节点的时候返回-1 递归…

Web3公链之Cosmos生态的项目Celestia

文章目录 Web3公链之Cosmos生态的项目&#xff1a;模块化区块链Celestia什么是CelestiaCelestia网络架构数据可用性问题有哪些可用的解决方案&#xff1f; 发展历史运行节点参考 Web3公链之Cosmos生态的项目&#xff1a;模块化区块链Celestia 什么是Celestia 官网&#xff1a…

Go学习第十七章——Gin中间件与路由

Go web框架——Gin中间件与路由 1 单独注册中间件1.1 入门案例1.2 多个中间件1.3 中间件拦截响应1.4 中间件放行 2 全局注册中间件3 自定义参数传递4 路由分组4.1 入门案例4.2 路由分组注册中间件4.3 综合使用 5 使用内置的中间件6 中间件案例权限验证耗时统计 1 单独注册中间件…

驱动day10作业

基于platform驱动模型完成LED驱动的编写 驱动程序 #include <linux/init.h> #include <linux/module.h> #include<linux/platform_device.h> #include<linux/mod_devicetable.h> #include<linux/of.h> #include<linux/of_gpio.h> #inclu…

【CSS】包含块

CSS规范中的包含块 包含块的内容&#xff1a; 元素的尺寸和位置&#xff0c;会受它的包含块所影响。 对于一些属性&#xff0c;例如 width, height, padding, margin&#xff0c;绝对定位元素的偏移值&#xff08;比如 position 被设置为 absolute 或 fixed&#xff09;&…

【原创】java+swing+mysql无偿献血管理系统设计与实现

摘要&#xff1a; 无偿献血管理系统是为了实现无偿献血规范化、有序化、高效化的管理而设计的。本文主要介绍使用java语言开发一个基于C/S架构的无偿献血管理系统&#xff0c;提高无偿献血管理的工作效率。 功能分析&#xff1a; 系统主要提供给管理员、无偿献血人员&#x…

【Mybatis-Plus】代码生成器

目录 安装插件 数据库建表 Other Config Database Code Generator 根据创建好的数据库表&#xff0c;来直接生成代码 安装插件 数据库建表 Other 点开之后有两个功能 1.数据库配置 2.代码生成 Config Database 首先点开这个配置数据库 Code Generator 配置完数据库…

数据结构第一课-----------数据结构的介绍

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

Web自动化测试进阶 —— Selenium模拟鼠标操作

鼠标操作事件 在实际的web产品测试中&#xff0c;对于鼠标的操作&#xff0c;不单单只有click()&#xff0c;有时候还要用到右击、双击、拖动等操作&#xff0c;这些操作包含在ActionChains类中。 ActionChains类中鼠标操作常用方法&#xff1a; 首先导入ActionChains类&…

Redis持久化(RDB、AOF)

一、RDB RDB&#xff1a;Redis数据备份文件&#xff0c;也叫Redis数据快照&#xff0c;简单来说就是把内存数据保存的磁盘上&#xff0c;当Redis故障重启后&#xff0c;从磁盘中读取快照并恢复数据到Redis中。 RDB有两种启动命令&#xff1a; save&#xff1a;由Redis主进程…

黑马 小兔鲜儿 uniapp 小程序开发- 商品详情模块- day05

黑马 小兔鲜儿 uniapp 小程序开发- 分类模块- day04-CSDN博客 小兔鲜儿 - 商品详情(登录前)-day05 商品详情页分为两部分讲解&#xff1a; 登录前&#xff1a;展示商品信息&#xff0c;轮播图交互&#xff08;当前模块&#xff09;登录后&#xff1a;加入购物车&#xff0c;立…

机器视觉能不能再火爆?大多数企业订单减少是现实,大多数企业维持现有的经营状态将会非常困难,就看人工智能和新兴产业能不能破门而入

每个人都讲机器视觉代替大量人工&#xff0c;可是真的吗&#xff1f;没有订单&#xff0c;人工的存在都没必要&#xff0c;需要什么机器视觉检测。 我们首先有一个问题&#xff0c;机器视觉行业之前有没有火爆过&#xff1f; 有&#xff0c;但是出现短暂之后是内卷。深度学习A…

LeetCode字符串题库 之 罗马数字转整数

题目链接&#x1f517;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 1. 题目分析 我们在做题的时候&#xff0c;一定要知道题目的目的是什么&#xff0c;我们可以结合测试用例和提示来看。 我们可以分析以下几点&#xff1a; 1. 每一个罗马数字都…

【Java】LinkedList 集合

LinkedList集合特点 LinkedList 底层基于双向链表实现增删 效率非常高&#xff0c;查询效率非常低。 LinkedList源码解读分析 LinkedList 是双向链表实现的 ListLinkedList 是非线程安全的&#xff08;线程是不安全的&#xff09;LinkedList 元素允许为null,允许重复元素Linked…

2023-在mac下安装Homebrew的国内镜像

mac安装Homebrew的国内镜像 尝试使用其他下载源&#xff1a;GitHub 可能会受到访问限制&#xff0c;尝试使用其他镜像或下载源。您可以使用清华大学、中科大或阿里云的 Homebrew 镜像&#xff0c;以提高下载速度和可靠性。例如&#xff0c;可以使用阿里云的镜像来安装 Homebre…

HTML5+CSS3+Vue小实例:路飞出海的动画特效

实例:路飞出海的动画特效 技术栈:HTML+CSS+Vue 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&…

亚马逊云科技为奇点云打造全面、安全、可扩展的数据分析解决方案

刘莹奇点云联合创始人、COO&#xff1a;伴随云计算的发展&#xff0c;数据技术也在快速迭代&#xff0c;成为客户迈入DT时代、实现高质量发展的关键引擎。我们很高兴能和云计算领域的领跑者亚马逊云科技一同&#xff0c;不断为客户提供安全可靠的产品与专业的服务。 超过1500家…

【广州华锐互动】飞机诊断AR远程指导系统为工程师提供更多支持

随着科技的发展&#xff0c;飞机的维护工作也在不断进步。其中&#xff0c;AR&#xff08;增强现实&#xff09;技术的应用使得远程运维成为可能。本文将探讨AR在飞机诊断远程指导系统中的应用&#xff0c;以及它对未来航空维护模式的影响。 AR远程指导系统是一种使用增强现实技…

云安全—K8S API Server 未授权访问

0x00 前言 master节点的核心就是api服务&#xff0c;k8s通过REST API来进行控制&#xff0c;在k8s中的一切都可以抽象成api对象&#xff0c;通过api的调用来进行资源调整&#xff0c;分配和操作。 通常情况下k8s的默认api服务是开启在8080端口&#xff0c;如果此接口存在未授…