加密与安全_双向RSA+AES加密及Code实现

news2024/12/23 1:53:17

文章目录

  • AES / RSA
  • 流程
  • Code
    • 生成AES密钥 和 生成RSA密钥对
    • AES工具类,提供AES加密和解密功能
    • RSA加密工具类
    • 测试类
  • 总结

在这里插入图片描述


AES / RSA

  • AES:一种对称加密算法,意味着加密和解密使用相同的密钥。速度快,适合加密大量数据。
  • RSA:一种非对称加密算法,有一对密钥:公钥和私钥。用公钥加密的数据只能用对应的私钥解密,反之亦然。

流程

在这里插入图片描述

  1. 客户端和服务端都生成一对RSA密钥

    • 客户端和服务端各自生成自己的RSA公钥和私钥。
    • RSA公钥是公开的,可以共享;RSA私钥则要保密。
  2. 客户端和服务端分别生成AES密钥

    • 客户端和服务端都生成自己的AES密钥,用于加密实际的数据。
  3. 客户端发送请求给服务端

    • 客户端用服务端的RSA公钥加密它自己的AES密钥,并将加密后的AES密钥发送给服务端。
    • 同时,客户端还会用AES密钥加密一份请求报文,然后将这个加密的报文和它自己的RSA公钥一起发送给服务端。
  4. 服务端解密并处理请求

    • 服务端接收到请求后,用自己的RSA私钥解密客户端发送的AES密钥。
    • 然后,服务端用解密后的AES密钥解密客户端的请求报文,得到了客户端发送的实际信息。
    • 服务端接下来会生成一个响应报文,用客户端的AES密钥加密该响应报文。
  5. 服务端发送响应给客户端

    • 服务端用客户端的RSA公钥加密自己的AES密钥,并将加密后的AES密钥和加密的响应报文一起发送给客户端。
  6. 客户端解密并获取响应

    • 客户端用自己的RSA私钥解密服务端发送过来的AES密钥。
    • 然后,客户端用解密后的AES密钥解密服务端的响应报文,得到最终的回应内容。

Code

在这里插入图片描述

生成AES密钥 和 生成RSA密钥对

package com.artisan.shuangxiang_aesrsa;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

/**
 * @author artisan
 */
public class KeyGeneration {
    /**
     * 生成AES密钥
     *
     * @return 生成的SecretKey对象,包含AES算法的密钥
     * @throws Exception 如果密钥生成过程中出现错误
     */
    public static SecretKey generateAESKey() throws Exception {
        // 获取KeyGenerator实例,指定使用AES算法
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        // 初始化AES密钥的长度为128位
        keyGen.init(128);
        // 生成AES密钥
        return keyGen.generateKey();
    }


    /**
     * 生成RSA密钥对
     *
     * @return 生成的RSA密钥对
     * @throws Exception 如果无法生成密钥对,则抛出异常
     */
    public static KeyPair generateRSAKeyPair() throws Exception {
        // 获取密钥对生成器实例
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器为2048位
        keyPairGen.initialize(2048);
        // 生成RSA密钥对
        return keyPairGen.generateKeyPair();
    }
}


AES工具类,提供AES加密和解密功能

package com.artisan.shuangxiang_aesrsa;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.util.Base64;

/**
 * @author artisan
 */
/**
 * AES工具类,提供AES加密和解密功能
 * 使用AES/CBC/PKCS5Padding算法进行加密和解密
 */
public class AESUtil {
    /**
     * 定义加密算法类型为AES/CBC/PKCS5Padding
     */
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
     * 使用AES算法加密数据
     *
     * @param data 待加密的字符串
     * @param key 加密使用的SecretKey
     * @param iv 加密使用的初始化向量(IvParameterSpec)
     * @return 加密后的字符串,以Base64编码
     * @throws Exception 如果加密过程中发生错误,抛出异常
     */
    public static String encryptAES(String data, SecretKey key, IvParameterSpec iv) throws Exception {
        // 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 初始化Cipher为加密模式,传入密钥和初始化向量
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        // 将待加密数据转换为字节数组,并执行加密操作
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        // 将加密后的数据使用Base64编码,并返回
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用AES算法解密数据
     *
     * @param encryptedData 待解密的字符串,以Base64编码
     * @param key 解密使用的SecretKey
     * @param iv 解密使用的初始化向量(IvParameterSpec)
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中发生错误,抛出异常
     */
    public static String decryptAES(String encryptedData, SecretKey key, IvParameterSpec iv) throws Exception {
        // 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 初始化Cipher为解密模式,传入密钥和初始化向量
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        // 将待解密数据从Base64解码为字节数组
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);
        // 执行解密操作
        byte[] decryptedData = cipher.doFinal(decodedData);
        // 将解密后的数据转换为字符串,并返回
        return new String(decryptedData);
    }
}


RSA加密工具类

package com.artisan.shuangxiang_aesrsa;

import javax.crypto.Cipher;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

/**
 * RSA加密工具类
 * @author artisan
 */
public class RSAUtil {
    /**
     *  定义加密算法类型为RSA
     */
    private static final String ALGORITHM = "RSA";

    /**
     * 使用RSA算法和公钥加密数据
     *
     * @param data 待加密的字符串数据
     * @param publicKey 用于加密的公钥
     * @return 加密后的数据,以Base64编码的字符串形式表示
     * @throws Exception 如果加密过程中发生错误,抛出异常
     */
    public static String encryptRSA(String data, PublicKey publicKey) throws Exception {
        // 获取Cipher实例,指定使用RSA算法
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 初始化Cipher为加密模式,并使用指定的公钥
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        // 将待加密的字符串转换为字节数组,并执行加密操作
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        // 将加密后的字节数组使用Base64编码为字符串
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 使用RSA算法和私钥解密数据
     *
     * @param encryptedData 待解密的字符串数据,预期是通过Base64编码的
     * @param privateKey 用于解密的私钥
     * @return 解密后的原始字符串数据
     * @throws Exception 如果解密过程中发生错误,抛出异常
     */
    public static String decryptRSA(String encryptedData, PrivateKey privateKey) throws Exception {
        // 获取Cipher实例,指定使用RSA算法
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        // 初始化Cipher为解密模式,并使用指定的私钥
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        // 将Base64编码的字符串解码为字节数组
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);
        // 执行解密操作,得到原始的字节数组
        byte[] decryptedData = cipher.doFinal(decodedData);
        // 将解密后的字节数组转换为字符串
        return new String(decryptedData);
    }
}


测试类

package com.artisan.shuangxiang_aesrsa;

import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

/**
 * @author artisan
 */
public class Main {


    /**
     * 使用RSA公钥加密AES密钥,以及使用RSA私钥解密AES密钥的全过程
     * 同时展示了使用AES密钥加密和解密数据的应用
     *
     * @param args 命令行参数
     * @throws Exception 可能抛出的异常
     */
    public static void main(String[] args) throws Exception {
        // 生成AES和RSA密钥
        SecretKey aesKey = KeyGeneration.generateAESKey();
        KeyPair rsaKeyPair = KeyGeneration.generateRSAKeyPair();
        PublicKey rsaPublicKey = rsaKeyPair.getPublic();
        PrivateKey rsaPrivateKey = rsaKeyPair.getPrivate();

        String aesKeyString = Base64.getEncoder().encodeToString(aesKey.getEncoded());
        System.out.println("AES密钥: " + aesKeyString);
        // 初始化IV(通常需要确保IV的安全传输)  16字节的IV向量
        IvParameterSpec iv = new IvParameterSpec(new byte[16]);

        // 客户端用服务端的RSA公钥加密AES密钥
        String encryptedAESKey = RSAUtil.encryptRSA(aesKeyString, rsaPublicKey);
        System.out.println("加密后的AES密钥: " + encryptedAESKey);

        // 模拟服务端解密AES密钥
        String decryptedAESKey = RSAUtil.decryptRSA(encryptedAESKey, rsaPrivateKey);
        SecretKey originalAESKey = new javax.crypto.spec.SecretKeySpec(Base64.getDecoder().decode(decryptedAESKey), "AES");
        System.out.println("解密后的AES密钥: " + Base64.getEncoder().encodeToString(originalAESKey.getEncoded()));

        // 使用AES加密和解密数据
        String originalData = "我是需要加密的数据artisan GO GO GO !!!";
        String encryptedData = AESUtil.encryptAES(originalData, aesKey, iv);
        System.out.println("加密的数据: " + encryptedData);

        String decryptedData = AESUtil.decryptAES(encryptedData, aesKey, iv);
        System.out.println("解密的数据: " + decryptedData);
    }
}


输出

AES密钥: n5PbFsDPACXiDsuBhjHwvg==
加密后的AES密钥: cuNuyggZpGhVthHpUPEEt7l7Nh9ySl4S4zLBVLpxbx3ft9JwKNfTi0ggtAX1p27lpFsru/riYVv/6HuI/AO2PV/WzmE9ySUa7+cdkvlTqdbsQaFF67R2DqEtMbsJyfiGVI6Y9acObMWw9nGeggtsQAlfNqjV8LC8i1T4OJcstMcmdgCEg85vBizwdFEOJPZO1SDEd///CY2jT7tY7Zz4kvq9f+WkNnHy+s11cUOzr6Griv83JlFNPvJ3DifVhkmxsR5Cg9HaRtjSRvx9VPfwza/SrQWue7rzsLSirXsj+kIOBfOopSFj0xSBCG32NnQEuWspSGdgJTHAmD/X7RJzoQ==
解密后的AES密钥: n5PbFsDPACXiDsuBhjHwvg==
加密的数据: a1gn+70y0nkd9VGg3hg3Y/b0PxUd1dqAuzKHDedGMdleu2UVWkBtInZ0Ox4iNOFM
解密的数据: 我是需要加密的数据artisan GO GO GO !!!

总结

这个流程的核心在于:

  • 使用RSA来安全地交换AES密钥
  • AES用来加密实际的数据,确保数据传输的安全性和效率
  • 请注意保护好自己的私钥,不可泄露

通过这种双向加密的方式,客户端和服务端能够安全地互相传递敏感信息,同时确保即使通信内容被截获,也无法被解读。

在这里插入图片描述

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

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

相关文章

Tina-Linux Bootloaer简述

Tina-Linux Bootloaer简述 目录介绍 ubuntuubuntu1804:~/tina-v2.0-sdk/lichee/brandy-2.0$ tree -L 1 . ├── build.sh ├── opensbi ├── spl //boot0 ├── spl-pub //boot0 ├── tools └── u-boot-2018 /ubootTina-Linux 启动流程简述

ant design pro v6 如何做好角色管理

先上图: 整个角色管理是如何做的吗? 首先你要处理后端,要先把角色存到用户那。 这是用户管理部分的内容: 可以看到一个用户是有多个角色的。 看到没有,存的是数组 数组的是一个 role 对象 role 对象是这样&#xf…

reactive 和 ref 的区别和联系

在 Vue3 的组合式 API (Composition API)中,ref 和 reactive 是用于创建响应式数据的两个核心函数。尽管二者都用于实现响应式数据,但在使用方式和适用场景上存在一些区别。 1. 基本概念 1.1 ref 用途:用于定义 基本…

深入探讨视频美颜SDK:直播美颜工具的核心技术与实现

本篇文章,笔者将深入探讨视频美颜SDK的核心技术及其在直播美颜工具中的实现。 一、视频美颜SDK的核心技术 视频美颜SDK通过一系列复杂的算法和技术,实时处理视频流并应用各种美颜效果。这些核心技术主要包括以下几个方面: 1.人脸识别与追踪…

【Hot100】LeetCode—24. 两两交换链表中的节点

目录 1- 思路四指针 2- 实现⭐24. 两两交换链表中的节点——题解思路 3- ACM 实现 原题连接:24. 两两交换链表中的节点 1- 思路 四指针 定义 dummyHead:便于处理头结点① cur 指针,记录两个交换节点的前 前一个结点② 第一个指针 first③ 第…

嵌入式开发--STM32G030C8T6,写片上FLASH死机CFGBSY和写入出错

故障现象1 G0系列,写片上FLASH时,经常死机,而且按复位键都没用,属于不断电都救不回来的那种死法。这种情况一般是由硬件置位了某个标志导致,只有断电才能故障复原。 故障查找 检查FLASH的相关寄存器,发现…

【秋招笔试】8.18大疆秋招(第一套)-后端岗

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…

树莓派Pico C/C++ 开发环境搭建(一键完成版)

树莓派Pico C/C 开发环境搭建(一键完成版) 因为之前使用过MicroPython开发过树莓派Pico,总觉得用起来怪怪的。正好最近树莓怕发布了新一代的MCU——RP2350,之前的RP2040在各个平台都有所降价,因此,买了几块。同时因为之前是玩stm…

【系统架构设计】系统分析与设计方法

【系统架构设计】系统分析与设计方法 定义问题与归结模型问题分析因果鱼骨图 帕累托图上下文范围图 问题定义 需求分析与软件设计结构化分析与设计结构化分析DFD数据字典技术 结构化设计结构图程序流程图和盒图 模块设计 面向对象的分析与设计用户界面设计 定义问题与归结模型…

Eureka 原理与实践全攻略

一、Eureka 概述 Eureka 在微服务架构中具有举足轻重的地位。它作为服务注册与发现的核心组件,为分布式系统中的服务管理提供了关键支持。 Eureka 的主要功能包括服务注册、服务发现、服务健康监测和自我保护机制。服务注册功能使得服务提供者能够在启动时将自身的…

Linux安装配置docker,k8s

1.linux虚拟机初始配置 详情操作见下,具体操作需要注意 1.网络模式选择 NAT模式(对应第8点) 2.不用选择安装 GUI图形界面 (对应19点-5) 3.分区非必须操作 可以不分区(对应20点) 4.打开网络开关 (对应23点) CentOS 7安装教程&#xff…

利用GPTs,打造你的专属AI聊天机器人

在2023年11月的「OpenAI Devday」大会上,OpenAI再度带来了一系列令人瞩目的新功能,其中ChatGPT方面的突破尤为引人关注。而GPTs的亮相,不仅标志着个性化AI时代的到来,更为开发者和普通用户提供了前所未有的便利。接下来&#xff0…

C语言-部分字符串函数详解 1-4

C语言-部分字符串函数详解 1-4 前言1.strlen1.1基本用法1.2注意事项\0size_t 1.3模拟实现 2.strcpy2.1基本用法2.2注意事项**源字符串必须以 \0 结束****会将源字符串中的 \0拷贝到目标空间****目标空间必须可修改****目标空间必须能容纳下源字符串的内容** 2.3模拟实现 3.strn…

ES 模糊查询 wildcard 的替代方案探索

一、Wildcard 概述 Wildcard 是一种支持通配符的模糊检索方式。在 Elasticsearch 中,它使用星号 * 代表零个或多个字符,问号 ? 代表单个字符。 其使用方式多样,例如可以通过 {"wildcard": {"field_name": "value&…

【数据结构】关于冒泡排序,选择排序,插入排序,希尔排序,堆排序你到底了解多少???(超详解)

前言: 🌟🌟Hello家人们,这期讲解排序算法的原理,希望你能帮到屏幕前的你。 🌈上期博客在这里:http://t.csdnimg.cn/I1Ssq 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-C…

RK3568平台开发系列讲解(PWM篇)PWM的使用

文章目录 一、什么是PWM二、RK3568 PWM2.1、PWM 通道与引脚2.2、PWM 简介2.3、PWM 设备节点三、RK3568 PWM 调试节点📢 PWM 是很常用到功能,我们可以通过 PWM 来控制电机速度,也可以使用 PWM 来控制 LCD 的背光亮度。 一、什么是PWM PWM 全称是 Pulse Width Modulation,也…

XSS- - - DOM 破坏案例与靶场

目录 链接靶场: 第一关 Ma Spaghet 第二关 Jefff 第三关 Ugandan Knuckles 第四关 Ricardo Milos 第五关 Ah Thats Hawt 第六关 Ligma 第七关 Mafia 第八关 Ok, Boomer 链接靶场: XS…

SmartEDA崛起!揭秘其逐步取代Multisim与Proteus的四大颠覆性优势

在电子设计自动化(EDA)的浩瀚星空中,两款老牌软件——Multisim与Proteus,长久以来如同璀璨的双星,引领着电路仿真与设计的潮流。然而,近年来,一颗新星悄然升起,以其独特的魅力与强大…

《向量数据库 Faiss 搭建与使用全攻略》

一、Faiss 概述 Faiss 是由 Facebook AI 团队开发的一款强大工具,在大规模数据处理和相似性搜索领域占据着重要地位。 在当今信息爆炸的时代,数据规模呈指数级增长,如何从海量数据中快速准确地找到相似的数据成为了关键挑战。Faiss 应运而生…

【MeterSphere】占用磁盘空间过大问题处理方式

目录 一、现象 二、 清理docker系统命令(效果不大) 三、 追踪文件 四、 处理logs(小处理) 五、 对比容器问题发现node容器问题 六、结果 前言:部署ms使用一段时间,服务器监控发现磁盘空间占用过大&am…