非对称加密、解密原理及openssl中的RSA示例代码
一、【原理简介】非对称加密
非对称加密,也被称为公钥加密,其中使用一对相关的密钥:一个公钥和一个私钥。公钥用于加密数据,私钥用于解密数据。公钥可以公开分享,而私钥必须保密。
-
密钥生成:
- 当一个用户或设备希望使用非对称加密时,要生成一对密钥:一个公钥和一个私钥。这两个密钥是数学上相关的,但从公钥中计算出私钥在计算上是不可行的。
-
加密过程:
- 发送方使用接收方的公钥对消息进行加密。只有持有与那个公钥相对应的私钥的人(在这种情况下是接收方)才能解密这个消息。
-
解密过程:
- 接收方使用其私钥对接收到的加密消息进行解密,以恢复原始消息。
-
安全性:
- 即使攻击者知道公钥并且他们拦截了加密的消息,但由于他们没有私钥,所以他们不能解密那个消息。这提供了保密性。
- 由于私钥不是公开的,因此无法用它来伪造加密的消息。
-
数字签名:
- 除了保密性外,非对称加密还可以用于数字签名。发送方使用其私钥对消息的哈希进行加密,产生一个数字签名。
- 接收方可以使用发送方的公钥来验证签名,确保消息是从发送方发出的,并且没有被修改。
-
主要算法:
- RSA、ElGamal、ECC(椭圆曲线加密)是非对称加密的主要算法。
-
性能问题:
- 与对称加密相比,非对称加密通常计算上更加昂贵,所以它在处理大量数据时可能不太实用。在实际场景中,经常使用非对称加密来交换一个对称密钥(如AES密钥),然后使用对称加密来加密实际的数据。
-
公钥基础设施(PKI):
- PKI是一个结合硬件、软件、策略和标准,以实现公钥加密和数字签名服务的体系结构。它包括证书颁发机构(CA),负责颁发和验证数字证书。
总结:非对称加密使用一对密钥来确保数据的安全性和完整性。公钥用于加密,而私钥用于解密或签名。
二、【代码】生成秘钥对文件 和 读取秘钥对加密、加密
- example 1 生成秘钥对
#include <stdio.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>/* compile : gcc createRSA_KeyPair.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
int main() {int ret = 0;RSA *r = NULL;BIGNUM *bne = NULL;int bits = 2048;unsigned long e = RSA_F4;// 1. 生成 RSA 密钥对bne = BN_new();ret = BN_set_word(bne, e);if(ret != 1) {goto free_all;}r = RSA_new();ret = RSA_generate_key_ex(r, bits, bne, NULL);if(ret != 1) {goto free_all;}// 2. 保存私钥到 PEM 文件FILE *fp = fopen("private_key.pem", "wb");if(fp == NULL) {perror("Unable to open private key file for writing");goto free_all;}PEM_write_RSAPrivateKey(fp, r, NULL, NULL, 0, NULL, NULL);fclose(fp);// 3. 保存公钥到 PEM 文件fp = fopen("public_key.pem", "wb");if(fp == NULL) {perror("Unable to open public key file for writing");goto free_all;}PEM_write_RSA_PUBKEY(fp, r);fclose(fp);free_all:RSA_free(r);BN_free(bne);return 0;
}
- example 2 使用秘钥对加密、解密
#include <stdio.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>/* compile : gcc keyFromFile.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
int main() {// 加载公钥FILE* pubKeyFile = fopen("public_key.pem", "rb");RSA* rsaPublicKey = PEM_read_RSA_PUBKEY(pubKeyFile, NULL, NULL, NULL);fclose(pubKeyFile);// 加载私钥FILE* privKeyFile = fopen("private_key.pem", "rb");RSA* rsaPrivateKey = PEM_read_RSAPrivateKey(privKeyFile, NULL, NULL, NULL);fclose(privKeyFile);const char* plainText = "Hello, OpenSSL!";char encrypted[4098] = {};char decrypted[4098] = {};// 使用公钥加密int encryptedLength = RSA_public_encrypt(strlen(plainText), (unsigned char*)plainText,(unsigned char*)encrypted, rsaPublicKey, RSA_PKCS1_OAEP_PADDING);if (encryptedLength == -1) {printf("Public Encrypt failed \n");return 0;}// 使用私钥解密int decryptedLength = RSA_private_decrypt(encryptedLength, (unsigned char*)encrypted,(unsigned char*)decrypted, rsaPrivateKey, RSA_PKCS1_OAEP_PADDING);if (decryptedLength == -1) {printf("Private Decrypt failed \n");return 0;}decrypted[decryptedLength] = '\0';printf("Original: %s\n", plainText);printf("Decrypted: %s\n", decrypted);RSA_free(rsaPublicKey);RSA_free(rsaPrivateKey);return 0;
}
三、【代码】代码内生成秘钥对并加密解密
- c风格
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>/* compile : gcc RSA.c -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
int main() {// 1. create keyint ret = 0;RSA *rsa = NULL;BIGNUM *bne = NULL;int bits = 2048;unsigned long e = RSA_F4;bne = BN_new();ret = BN_set_word(bne, e);if(ret != 1) {goto free_all;}rsa = RSA_new();ret = RSA_generate_key_ex(rsa, bits, bne, NULL);if(ret != 1) {goto free_all;}// 2. encryptoconst char* plainText = "Hello, OpenSSL!";char encrypted[4098] = {};int encryptedLength = RSA_public_encrypt(strlen(plainText) + 1, (unsigned char*)plainText,(unsigned char*)encrypted, rsa, RSA_PKCS1_OAEP_PADDING);if(encryptedLength == -1) {printf("Public Encrypt failed \n");goto free_all;}// 3. decryptochar decrypted[4098] = {};int decryptedLength = RSA_private_decrypt(encryptedLength, (unsigned char*)encrypted,(unsigned char*)decrypted, rsa, RSA_PKCS1_OAEP_PADDING);if(decryptedLength == -1) {printf("Private Decrypt failed \n");goto free_all;}decrypted[decryptedLength] = '\0';printf("Original: %s\n", plainText);printf("Decrypted: %s\n", decrypted);free_all:RSA_free(rsa);BN_free(bne);return 0;
}
- C++风格
#include <iostream>
#include <vector>
#include <stdexcept>extern "C"{
#include <openssl/pem.h>
#include <openssl/rsa.h>
}class RSAWrapper {
public:RSAWrapper() {rsa = RSA_new();bne = BN_new();BN_set_word(bne, RSA_F4);RSA_generate_key_ex(rsa, 2048, bne, nullptr);}~RSAWrapper() {RSA_free(rsa);BN_free(bne);}std::vector<unsigned char> encrypt(const std::string &plainText) {std::vector<unsigned char> encrypted(RSA_size(rsa));int encryptLength = RSA_public_encrypt(plainText.size(),reinterpret_cast<const unsigned char*>(plainText.c_str()),encrypted.data(),rsa,RSA_PKCS1_OAEP_PADDING);if (encryptLength == -1) {throw std::runtime_error("Error during encryption");}return encrypted;}std::string decrypt(const std::vector<unsigned char> &cipherText) {std::vector<unsigned char> decrypted(RSA_size(rsa));int decryptLength = RSA_private_decrypt(cipherText.size(),cipherText.data(),decrypted.data(),rsa,RSA_PKCS1_OAEP_PADDING);if (decryptLength == -1) {throw std::runtime_error("Error during decryption");}return std::string(reinterpret_cast<char*>(decrypted.data()));}private:RSA *rsa;BIGNUM *bne;
};/* compile : g++ -std=c++11 RSA.cpp -I./include -L./lib -lcrypto -Wl,-rpath=./lib */
int main() {try {RSAWrapper rsaWrapper;std::string plainText = "Hello, OpenSSL C++!";auto encrypted = rsaWrapper.encrypt(plainText);auto decrypted = rsaWrapper.decrypt(encrypted);std::cout << "Original Text: " << plainText << std::endl;std::cout << "Decrypted Text: " << decrypted << std::endl;} catch (const std::exception &e) {std::cerr << "Error: " << e.what() << std::endl;}return 0;
}
相关文章:
非对称加密、解密原理及openssl中的RSA示例代码
一、【原理简介】非对称加密 非对称加密,也被称为公钥加密,其中使用一对相关的密钥:一个公钥和一个私钥。公钥用于加密数据,私钥用于解密数据。公钥可以公开分享,而私钥必须保密。 密钥生成: 当一个用户或设备希望使用…...

基于springboot漫画管理系统springboot001
摘 要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&…...

【探索C++】string类详解
(꒪ꇴ꒪ ),Hello我是祐言QAQ我的博客主页:C/C语言,数据结构,Linux基础,ARM开发板,网络编程等领域UP🌍快上🚘,一起学习,让我们成为一个强大的攻城狮࿰…...

python 第一次作业
1.使用turtle换一个五环 2.设计这样一个程序:输入一个数字 判断它是不是一个质数 使用turtle换一个五环: >>> import turtle #导入模块 >>> turtle.width(10) #设置圆圈宽度 >>> turtle.color("blue&qu…...

个人博客网站一揽子:Docker建站(Nginx、Wordpress、MySql)
前言 既然安装了Docker,那就不妨建立一个自己的博客网站。实现内外网隔离网站部署,更安全。 1.创建Docker子网络 首先创建一个Docker虚拟子网: sudo docker network create wpnt检查是否建立成功: sudo docker network ls最后…...

Unity 课时 4 : No.4 模拟面试题
课时 4 : No.4 模拟面试题 C# 1. 请说明字符串中 string str null string str “” string str string.Empty 三者的区别 第一个未作初始化没有值, 第二个为空字符串, 答案: str null 在堆中没有分配内存地址 str "" 和 string.Empty 一样都是…...

Golang 基础面试题 01
Golang 面试题合集.png 背景 在之前的文章中分享了 k8s 相关的面试题,本文我们重点来讨论和 k8s 密切相关的 Go 语言面试题。 这几年随着云原生的兴起,大部分后端开发者,特别是 Java 开发者都或多或少的想学习一些 Go 相关的技能,…...

007-第一代软件需求整理
第一代软件需求整理 文章目录 第一代软件需求整理项目介绍需求来源需求来源1:竞品软件分析需求来源2:医生(市场)需求来源3:项目组内部需求来源4:软件组内部需求来源5:软件开发成员需求来源6&…...
XMLHttpRequest介绍
目录 一、介绍1.创建 XMLHttpRequest2.初始化3.发送请求4.获取响应5.响应类型 二、发送GET请求示例三、发送POST请求示例四、发送POST请求下载文件示例五、发送POST请求上传文件示例 一、介绍 1.创建 XMLHttpRequest let xhr new XMLHttpRequest();2.初始化 xhr.open(metho…...

阿里云无影云电脑和传统PC有什么区别?
阿里云无影云电脑和传统电脑PC有什么区别?区别大了,无影云电脑是云端的桌面服务,传统PC是本地的硬件计算机,无影云电脑的数据是保存在云端,本地传统PC的数据是保存在本地客户端,阿里云百科分享阿里云无影云…...

基于matlab实现的船舶横摇运动仿真程序
完整程序: clc clear syms w we; w0.4:0.05:1.6;mu90;v6;%kb1;kt1;%航速6m/s,航向90度,即横浪,cos(90)0 T3;B10;Sw0.785;%船宽10米,吃水3米,水线面系数假设为0.785 weww.^2.*v/9.8; for i1:24 delta_we(i)we(i1)-…...
Java手写二叉索引树和二叉索引树应用拓展案例
Java手写二叉索引树和二叉索引树应用拓展案例 1. 算法思维导图 以下为二叉索引树的实现原理的思维导图,使用Mermanid代码表示: #mermaid-svg-raMRIu7t3H33MKh1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#…...

大数据知识点之大数据5V特征
大数据的特征可以浓缩为五个英文单词,Volume(大量)、Variety(多样性)、Velocity(速度)、Value(价值)、Veracity(准确性)。因为是5个特征都是以“V”开头的英文单词,又叫大数据5V特征。 概述&…...

Java的Socket通信的断网重连的正确写法
Java的Socket通信的断网重连的正确写法 Socket通信的断网重连介绍客户端与服务端源码演示截图本地演示服务器演示演示截图 总结 Socket通信的断网重连介绍 针对于已经建立通信的客户端与服务器,当客户端与服务器因为网络问题导致网络不通而断开连接了或者由于服务器…...

Rocketmq--消息发送和接收演示
使用Java代码来演示消息的发送和接收 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.0.2</version> </dependency> 1 发送消息 消息发送步骤: 创建…...

ArcGIS Pro将SHP文件转CAD并保留图层名称
相信大家应该都使用过ArcGIS将SHP文件转CAD格式,转换过后所有的要素都在一个图层内,那么有没有办法将SHP文件某个字段的值作为CAD的图层名字呢,答案是肯定的,这里就为大家介绍一下ArcGIS Pro转CAD文件并且保留图层名称的方法&…...
GEE:使用for循环合成时间序列影像
作者:CSDN @ _养乐多_ 在本博客中,我们将介绍如何使用Google Earth Engine创建一个时间序列图像集合,以便进行时间序列分析或生成动态图像。 文章目录 一、核心代码二、代码解释三、示例代码链接一、核心代码 // 创建一个空的 image 图像集合 var imagelist = ee.List([])…...
flink1.13.2版本的对应的hive的Hcatalog的使用记录
依赖版本要求<hive.version>3.1.2</hive.version><flink.version>1.13.2</flink.version><hadoop.version>3.3.2</hadoop.version><scala.binary.version...

STM32 ADC介绍和应用
目录 1.ADC是什么? 2.ADC的性能指标 3.ADC特性 4.ADC通道 5.ADC转换顺序 6.ADC触发方式 7.ADC转化时间 8.ADC转化模式 扫描模式 单次转换/连续转换 9.ADC实验 使用ADC读取烟雾传感器的值 代码实现思路: 1.ADC是什么? 全称&#…...

vue项目打包_以生产环境prod模式打包_vue-cli-service 不是内部或外部命令,也不是可运行的程序---vue工作笔记0025
打开命令行: 首先执行npm install 不执行会报错: npm run build:prod --scripts-prepend-node-pathauto 然后再这样执行就是以生产环境模式打包了....

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...

Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...

作为点的对象CenterNet论文阅读
摘要 检测器将图像中的物体表示为轴对齐的边界框。大多数成功的目标检测方法都会枚举几乎完整的潜在目标位置列表,并对每一个位置进行分类。这种做法既浪费又低效,并且需要额外的后处理。在本文中,我们采取了不同的方法。我们将物体建模为单…...