openssl对称加密代码讲解实战

news2024/11/14 5:41:16

文章目录

  • 一、openssl对称加密和非对称加密算法对比
      • 1. 加密原理
      • 2. 常用算法
      • 3. 加密速度
      • 4. 安全性
      • 5. 应用场景
      • 6. 优缺点对比
      • 综合分析
  • 二、代码实战
      • 代码说明:
      • 运行输出示例
      • 代码说明:
      • 注意事项


一、openssl对称加密和非对称加密算法对比

OpenSSL 是一个广泛使用的加密库,提供了丰富的对称加密和非对称加密算法。这两类加密方式各有不同的特点和适用场景。以下是两者的对比:

1. 加密原理

  • 对称加密

    • 使用相同的密钥进行加密和解密。
    • 密钥在加密和解密双方之间共享,因此需要一个安全的密钥传输方式。
    • 加密速度较快,适合加密大量数据。
  • 非对称加密

    • 使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密。
    • 公钥可以公开,私钥则需要保护,只有拥有私钥的人才能解密公钥加密的数据。
    • 适合小数据量加密和签名,但处理大数据效率较低。

2. 常用算法

  • 对称加密算法(在 OpenSSL 中支持的常见算法):

    • AES(高级加密标准):流行且安全的对称加密算法,支持 128、192 和 256 位密钥长度。
    • SM4:主要用于中国的商用密码标准,采用 128 位密钥。
    • DES 和 3DES(数据加密标准及三重数据加密标准):早期的加密算法,但已不再安全,较少使用。
  • 非对称加密算法(在 OpenSSL 中支持的常见算法):

    • RSA:广泛使用的非对称算法,密钥长度通常为 2048 或 4096 位。
    • ECC(椭圆曲线加密):基于椭圆曲线的加密,密钥较短但安全性高,用于资源受限的环境。
    • DSA(数字签名算法):主要用于签名,常见于数字证书。

3. 加密速度

  • 对称加密

    • 对称加密算法如 AES 在处理速度上显著优于非对称加密,非常适合大文件或大量数据的加密。
    • 常用于文件加密、数据存储、网络数据传输加密等场景。
  • 非对称加密

    • 非对称加密算法处理速度慢,因为其运算更为复杂,适合小数据量的加密,如数字签名和密钥交换。
    • 在实际应用中,通常将其与对称加密结合使用,通过非对称加密传输对称密钥来实现安全的密钥交换,后续的数据传输则使用对称加密。

4. 安全性

  • 对称加密

    • 安全性依赖于密钥长度和算法设计;例如,AES-256 被认为是非常安全的对称加密算法。
    • 密钥必须在传输中保持安全,一旦密钥泄露,数据的机密性将受到威胁。
  • 非对称加密

    • 安全性依赖于密钥长度和密钥保护。比如 RSA-2048 被认为是安全的,而 ECC 则以较短密钥提供更高安全性。
    • 私钥的安全性至关重要,如果私钥泄露,任何持有公钥的人都可以解密数据。

5. 应用场景

  • 对称加密的应用场景

    • 用于 HTTPS 中的数据加密(结合非对称加密交换密钥后)。
    • 云存储、数据库等大文件的加密保护。
    • VPN、WiFi 等网络传输中对数据的加密。
  • 非对称加密的应用场景

    • 数字签名,用于认证数据的来源和完整性。
    • SSL/TLS 协议中,用于加密对称加密密钥并验证通信双方身份。
    • 数据加密用于保护敏感信息的小文件,例如加密密码、密钥或数字证书。

6. 优缺点对比

对比项目对称加密非对称加密
密钥数量1 个密钥,共享密钥1 对密钥(公钥和私钥)
加密速度快,适合大数据慢,适合小数据
安全性密钥泄露会导致数据泄密公钥泄露不会影响数据的私密性
密钥分配需要安全的密钥传输私钥无需传输,安全性更高
典型应用大数据文件的加密、VPN、存储加密SSL/TLS、数字签名、密钥交换

综合分析

OpenSSL 中通常结合对称加密和非对称加密,以实现性能与安全性兼备的加密方案。例如,在 SSL/TLS 协议中,服务器会先使用非对称加密交换密钥,然后使用对称加密传输数据。

二、代码实战

下面是使用 OpenSSL 实现对称加密的示例代码,采用 AES-256-CBC 算法对数据进行加密。此代码会生成一个随机的初始向量(IV),并且使用固定的密钥对数据加密。

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define AES_KEY_LENGTH 32  // AES-256, so 256 bits = 32 bytes
#define AES_BLOCK_SIZE 16

void handleErrors() {
    ERR_print_errors_fp(stderr);
    abort();
}

// 对称加密函数
int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
                unsigned char *iv, unsigned char *ciphertext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int ciphertext_len;

    // 创建并初始化上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    // 初始化加密操作,指定 AES-256-CBC 算法
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();

    // 加密数据
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    // 完成加密
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
    ciphertext_len += len;

    // 释放上下文
    EVP_CIPHER_CTX_free(ctx);
    return ciphertext_len;
}

int main() {
    // 32 字节的密钥 (256 位)
    unsigned char key[AES_KEY_LENGTH] = "0123456789abcdef0123456789abcdef";
    
    // 生成 16 字节的初始向量 (128 位)
    unsigned char iv[AES_BLOCK_SIZE];
    if (!RAND_bytes(iv, AES_BLOCK_SIZE)) {
        fprintf(stderr, "随机生成初始向量失败\n");
        return 1;
    }

    unsigned char plaintext[] = "This is the data to encrypt";  // 要加密的数据
    unsigned char ciphertext[128];  // 存储密文的缓冲区

    // 执行加密操作
    int ciphertext_len = aes_encrypt(plaintext, strlen((char *)plaintext), key, iv, ciphertext);

    // 打印初始向量
    printf("Initial Vector (IV): ");
    for (int i = 0; i < AES_BLOCK_SIZE; i++) {
        printf("%02x ", iv[i]);
    }
    printf("\n");

    // 打印加密后的数据(密文)
    printf("Ciphertext (hex): ");
    for (int i = 0; i < ciphertext_len; i++) {
        printf("%02x ", ciphertext[i]);
    }
    printf("\n");

    return 0;
}

代码说明:

  • 初始化加密上下文:使用 EVP_CIPHER_CTX_new() 创建加密上下文。
  • 设置加密算法和密钥:通过 EVP_EncryptInit_ex() 指定 AES-256-CBC 算法。
  • 加密数据EVP_EncryptUpdate() 用于加密数据块。
  • 完成加密EVP_EncryptFinal_ex() 处理最后的数据块。
  • 生成随机初始向量(IV)RAND_bytes() 生成随机 IV,确保加密的安全性。

运行输出示例

Initial Vector (IV): 1a 2b 3c 4d ... (随机生成)
Ciphertext (hex): ae f5 67 89 ... (加密后的密文)

注意:密钥和初始向量(IV)应安全存储,并且应仅与需要解密的接收方共享。

这是对应解密代码,解密前需要与加密代码相同的密钥和初始向量(IV),用相同的算法参数对密文进行解密:

#include <openssl/evp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define AES_KEY_LENGTH 32  // 256 位密钥
#define AES_BLOCK_SIZE 16  // AES 块大小 128 位(16 字节)

void handleErrors() {
    ERR_print_errors_fp(stderr);
    abort();
}

// 对称解密函数
int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
                unsigned char *iv, unsigned char *plaintext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;

    // 创建并初始化上下文
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

    // 初始化解密操作,使用 AES-256-CBC 算法
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();

    // 提供待解密的数据
    if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleErrors();
    plaintext_len = len;

    // 完成解密操作
    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
    plaintext_len += len;

    // 清理上下文
    EVP_CIPHER_CTX_free(ctx);
    return plaintext_len;
}

int main() {
    // 密钥和 IV 与加密时保持一致
    unsigned char key[AES_KEY_LENGTH] = "0123456789abcdef0123456789abcdef";
    unsigned char iv[AES_BLOCK_SIZE] = {0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f, 0x7a, 0x8b,
                                        0x9c, 0xad, 0xbe, 0xcf, 0xde, 0xef, 0xfa, 0x1b};

    unsigned char ciphertext[] = {0xae, 0xf5, 0x67, 0x89, /* ... 加密数据的字节数组 */};
    unsigned char decryptedtext[128];  // 缓冲区用于存储解密后的明文

    // 执行解密操作
    int decryptedtext_len = aes_decrypt(ciphertext, sizeof(ciphertext), key, iv, decryptedtext);

    // 添加字符串终止符
    decryptedtext[decryptedtext_len] = '\0';

    // 输出解密后的明文
    printf("Decrypted text: %s\n", decryptedtext);

    return 0;
}

代码说明:

  • 初始化解密上下文:使用 EVP_CIPHER_CTX_new() 创建解密上下文。
  • 设置解密算法和密钥:通过 EVP_DecryptInit_ex() 指定 AES-256-CBC 算法。
  • 解密数据EVP_DecryptUpdate() 用于处理密文的主要部分。
  • 完成解密EVP_DecryptFinal_ex() 处理最后的数据块,并将明文长度加到总长度中。
  • 输出解密结果:解密后的数据存储在 decryptedtext 中,作为原始的明文数据输出。

注意事项

  • 密钥和初始向量(IV)必须与加密时一致。
  • 输出的解密文本会和加密前的原始文本一致。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自然语言处理在客户服务中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 引言 自然语言处理概述 定义…

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器&#xff0c;将OpenCV中lib库里的o…

【含文档】基于ssm+jsp的校园疫情管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: apache tomcat 主要技术: Java,Spring,SpringMvc,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定义了两个…

在Django中安装、配置、使用CKEditor5,并将CKEditor5录入的文章展现出来,实现一个简单博客网站的功能

在Django中可以使用CKEditor4和CKEditor5两个版本&#xff0c;分别对应软件包django-ckeditor和django-ckeditor-5。原来使用的是CKEditor4&#xff0c;python manager.py makemigrations时总是提示CKEditor4有安全风险&#xff0c;建议升级到CKEditor5。故卸载了CKEditor4&…

网络管理之---3种网络模式配置

目标&#xff1a; 了解几个概念&#xff1a; 1.什么是IP&#xff1f;什么是IP地址&#xff1f; 2.什么是桥接、NAT、仅主机模式 3.端口&#xff1f; 4.什么是网络接口命名规则 5.网络管理器 IP&#xff1a;指网络之间互联的协议&#xff0c;是TCP/IP 体系中的网络协议 I…

统信UOS开发环境支持Electron

全面支持Electron开发环境,同时还提供了丰富的开发工具和开发资源,进一步提升工作效率。 文章目录 一、环境部署1. Electron应用开发介绍2. Electron开发环境安装安装Node.js和npm安装electron环境配置二、代码示例Electron开发案例三、常见问题一、环境部署 1. Electron应用…

三级等保安全解决方案,实施方案,整改方案(Word,PPT等相关资料学习)

信息系统进行三级等保的主要原因在于保障信息安全&#xff0c;维护国家安全和公共利益。三级等保是我国根据相关法律法规制定的信息安全等级保护制度中的一部分&#xff0c;旨在确保信息系统的完整性、可用性和保密性。通过三级等保&#xff0c;信息系统可以得到一系列的安全保…

优选算法合集————双指针(专题一)

题目一&#xff1a;移动零 题目描述&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输…

python基于深度学习的音乐推荐方法研究系统

需求设计 一款好的音乐推荐系统其目的是为用户进行合理的音乐推荐&#xff0c;普通的用户在登录到系统之后&#xff0c;能够通过搜索的方式获取与输入内容相关的音乐推荐&#xff0c;而以管理员登录到系统之后&#xff0c;则可以进行徐昂管的数据管理等内容操作。此次的需求主…

Docker 镜像和容器的导入导出及常用命令

Docker 镜像和容器的导入导出 1.1 镜像的导入导出 1.1.1 镜像的保存 通过镜像ID保存 方式一&#xff1a; docker save image_id > image-save.tar例如&#xff1a; rootUbuntu:/usr/local/docker/nginx# docker imagesREPOSITORY TAG IMAGE ID …

Java集合 List——针对实习面试

目录 Java集合 ListJava List的三种主要实现是什么&#xff1f;它们各自的特点是什么&#xff1f;Java List和Array&#xff08;数组&#xff09;的区别&#xff1f;Java List和Set有什么区别&#xff1f;ArrayList和Vector有什么区别&#xff1f;什么是LinkedList&#xff1f;…

超级干货O2OA数据中心-查询配置开发

O2OA提供的数据管理中心&#xff0c;可以让用户通过配置的形式完成对数据的汇总&#xff0c;统计和数据分组展现&#xff0c;查询和搜索数据形成列表数据展现。也支持用户配置独立的数据表来适应特殊的业务的数据存储需求。本文主要介绍如何在O2OA中开发和配置自定义数据查询语…

Unity中IK动画与布偶死亡动画切换的实现

在Unity游戏开发中&#xff0c;Inverse Kinematics&#xff08;IK&#xff09;是创建逼真角色动画的强大工具。同时&#xff0c;能够在适当的时候切换到布偶物理状态来实现死亡动画等效果&#xff0c;可以极大地增强游戏的视觉体验。本文将详细介绍如何在Unity中利用IK实现常规…

【ArcGISPro】单次将自己建立的工具箱添加至Arcpy中

新建工具箱 添加至Arcpy中 调用刚添加的工具箱

JVM的组成、字节码文件的组成

目录 java虚拟机的组成 字节码文件的组成 基础信息 常量池 字段 方法 属性 字节码相关的常用工具&#xff1a; 总结&#xff1a; 1、如何查看字节码文件&#xff1f; 2、字节码文件的核心组成有哪些&#xff1f; java虚拟机的组成 类加载器 ClassLoader运行时数据区…

新的服务器Centos7.6 安卓基础的环境配置(新服务器可直接粘贴使用配置)

常见的基础服务器配置之Centos命令 正常来说都是安装一个docker基本上很多问题都可以解决了&#xff0c;我基本上都是通过docker去管理一些容器如&#xff1a;mysql、redis、mongoDB等之类的镜像&#xff0c;还有一些中间件如kafka。下面就安装一个 docker 和 nginx 的相关配置…

Mysql COUNT() 函数详解

Mysql COUNT 函数详解 COUNT() 的几种用法COUNT(*)COUNT(1)COUNT(column)COUNT(*) 与 GROUP BYCOUNT(*) 与 GROUP BY 和 HAVING COUNT(expr) 的用法COUNT(DISTINCT expr)COUNT(expr) 带条件查询 写在最后 在使用Mysql的时候&#xff0c;作为开发者&#xff0c;聚合函数是肯定会…

yum下载时出现报错 Couldn‘t read a file:// file for file:///mnt/repodata/repomd.xml

得知说yum源指定的/mnt/没有镜像源 发现可能是镜像没有挂载成功 mount /dev/cdrom /mnt 清理一下缓存重新试一下 yum clean all yum install mod_ssl 解决

视觉SLAM数学基础

本文系统梳理从相机成像模型&#xff0c;通过不同图像帧之间的构造几何约束求解位姿变换&#xff0c;再根据位姿变换和匹配点还原三维坐标的过程&#xff0c;可以作为基于特征点法的视觉SLAM的数学基础。 1、相机成像模型 1.1、针孔相机模型 实际相机的成像方式通常很复杂&a…

书生大模型第四期闯关任务与笔记

书生大模型第四期闯关任务与笔记 入门岛第一关 Linux闯关任务&#xff1a;完成SSH连接与端口映射并运行hello_world.py笔记与过程SSH端口映射linux文件管理命令linux进程管理命令 第二关 Python闯关任务&#xff1a;Leetcode 383(笔记中提交代码与leetcode提交通过截图)闯关任务…