Java对称与非对称加密解密(AES与RSA)

news2024/9/19 10:58:22

尽可能预想所有残酷的可能性、因为现实永远让你无法预警,而且又吝于给人慈悲。——富坚义博

 今天我们讨论一下秘钥这个东西


一、对称加密技术与非对称加密技术简述

 加密技术可以分为对称与非对称两种。

对称加密、解密即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等。

而非对称技术的加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等。

二、对称加密技术与非对称加密技术的使用场景简述

为什么要有非对称加密,解密技术呢?

假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密。如果采用对称加密技术,那么加密与解密用的是同一把秘钥,除非B事先就知道A的秘钥,并且保存好,这样才可以解密A发来的消息。

由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题,而非对称技术的诞生就解决了这个问题,非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密。

这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道。这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开。而B想更换自己的秘要时也很方便,只须把公钥告诉大家就可以了。

那么,既然非对称加密如此之好,对称加密就没有存在的必要了吗,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差。那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用。

还是这个例子:

第一个场景(公钥加密):A要发送一个消息给B。

第一步:A先 生成一个对称秘钥,这个秘钥可以是随机生成的;

第二步:A用B的公钥加密第一步生成的这个对称秘钥; (事先生成公钥、私钥)

第三步:A把加密过的对称秘钥发给B; (Aes秘钥发给B)

第四步:A用第一步生成的这个对称秘钥加密实际要发的消息 (用aes加密)

第五步:A把用对称秘钥加密的消息发给B (加密内容发给B)

对于B

他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥,

然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全,又保证了效率。

第二个场景(私钥加密):B要发送一个消息给A。

第一步:B先生成一个对称秘钥,这个秘钥可以是随机生成的;

第二步:B用自己的私钥加密第一步生成的这个对称秘钥;

第三步:B把加密过的对称秘钥发给A;

第四步:B用第一步生成的这个对称秘钥加密实际要发的消息

第五步:B把用对称秘钥加密的消息发给A

对于A

他先收到B发来的对称秘钥,这个秘钥是用B的私钥加密过的,所以A需要用B的公钥来解密这个秘钥,

然后A又收到B发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全,又保证了效率。

三、Java实现使用的是AES的对称加密和RSA的非对称加密

接下来是Java实现:

我这个Java实现使用的是AES的对称加密和RSA的非对称加密(DES的对称加密实现方法和AES的是一样的,但是由于DES算法本身有缺陷,容易被破解,所以现在多用其升级版AES对称加密)

AES加密工具类封装

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
 
/**
 * 〈Function overview〉<br>
 *
 * @className: AESUtil
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 16:41
 */
public class AESUtil {
    /**
     *
     * home.php?mod=space&uid=952169 str 加密前数据
     * @param key 对称密钥,必须为16位
     * home.php?mod=space&uid=155549 返回加密后数据
     */
    public static String encrypt(String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.encryptBase64(str);
    }
 
    /**
     *
     * @param str 加密后的数据
     * @param key 盐,必须为16位
     * @return 返回解密后数据
     */
    public static String decrypt (String str,String key){
        AES aes = SecureUtil.aes(key.getBytes());
        return aes.decryptStr(str);
    }
}

RSA加密工具类封装

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import org.apache.commons.codec.binary.Base64;
import java.security.KeyPair;
 
/**
 * 〈Function overview〉<br>
 *
 * @className: RSA
 * @package: com.soft.team.base.encryption
 * @author: yuanzf
 * @date: 2022/3/16 15:02
 */
public class RSAUtil {
    private String publicKey;
    private String privateKey;
 
    /*有参构造方法,加解密时使用。公钥加密需用私钥解密,私钥加密需用公钥解密*/
    public RSAUtil(String publicKey,String privateKey){
        this.publicKey = publicKey;
        this.privateKey = privateKey;
    }
 
    /*无参构造方法,新建密钥对时使用*/
    public RSAUtil(){
        KeyPair pair = SecureUtil.generateKeyPair("RSA");
        publicKey = new String(Base64.encodeBase64(pair.getPublic().getEncoded()));
        privateKey= new String(Base64.encodeBase64((pair.getPrivate().getEncoded())));
    }
 
    /**
     *
     * @param str 加密前数据
     * @return 返回加密后数据
     */
    public String encrypt(String str){
        return SecureUtil.rsa(privateKey,publicKey).encryptBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }
 
    /**
     *
     * @param str 加密后的数据
     * @return 返回解密后数据
     */
    public String decrypt (String str){
        return SecureUtil.rsa(privateKey,publicKey).decryptStrFromBcd(str, privateKey!=null?KeyType.PrivateKey:KeyType.PublicKey);
    }
 
    public String getPublicKey() {
        return publicKey;
    }
    public String getPrivateKey() {
        return privateKey;
    }
}

测试类

import cn.hutool.core.util.RandomUtil;
import org.junit.Test;

/**
 * 加解密测试类
 * @author: song rose roy nba
 */
public class SerialUtilTest {
    /**
     * 测试方法
     * 使用公钥加密就必须使用私钥解密,使用私钥加密就必须使用公钥解密
     * 以下测试方式编写了私钥加密公钥解密,公钥加密私钥解密两种情况
     * 真实的业务场景一方持有私钥,一方持有公钥。因此不会存在两种密钥在一个线程里加解密的情况
     * 真实场景应该是加密方式一和解密方式二为一方,加密方式二和解密方式一为一方
     */
    @Test
    public void start(){
        /*获取aes对称密钥*/
        String aesKey = getRandomKey();
        System.out.println("我是aes对称密钥,请将我保存:"+aesKey);
        
        /*使用aes密钥对内容进行加密*/
        String content = AESUtil.encrypt("我是一封信,请将我加密后发送",aesKey);
        System.out.println("我是加密后的内容:"+content);
        
        /*生成rsa密钥对*/
        RSAUtil rsa = new RSAUtil();
        System.out.println("我是rsa公钥,请将我保存:"+rsa.getPublicKey());
        System.out.println("我是rsa私钥,请将我保存:"+rsa.getPrivateKey());
        
        /*rsa加密方式一 公钥加密,在第一个参数放入生成的公钥*/
        RSAUtil rsaUtil1 = new RSAUtil(rsa.getPublicKey(),null);
        String enContent1 = rsaUtil1.encrypt(aesKey);
        System.out.println("我是经过rsa公钥加密后的aes对称密钥,请将我保存:"+enContent1);
        
        /*rsa加密方式二 私钥加密,在第二个参数放入生成的私钥*/
        RSAUtil rsaUtil2 = new RSAUtil(null,rsa.getPrivateKey());
        String enContent2 = rsaUtil2.encrypt(aesKey);
        System.out.println("我是经过rsa私钥加密后的aes对称密钥,请将我保存:"+enContent2);
        
        /*解密方式一 私钥解密*/
        String deContent1 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa私钥解密后的aes对称密钥,请将我保存:"+deContent1);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent1));
        
        /*解密方式二 公钥解密*/
        String deContent2 = rsaUtil2.decrypt(enContent1);
        System.out.println("我是经过rsa公钥解密后的aes对称密钥,请将我保存:"+deContent2);
        System.out.println("我是解密后的内容:"+AESUtil.decrypt(content,deContent2));

    }
    /**
     * 随机生成aes的秘钥
     */
    private String getRandomKey() {
        return RandomUtil.randomString(16);
    }
}

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

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

相关文章

MySQL - 连表查询 Join On 详解

1. 连表查询详解 市面上有 7 种连表查询, 总共归为三大类 : 左查询 LEFT JOIN -- 以左表为基准右查询 RIGHT JOIN -- 以右表为基准交叉查询 INNER JOIN -- 查询两表都有的数据 操作描述inner join如果表中至少有一个匹配, 就返回行left join会从左表中返回所有的值…

IDEA 设置文件头的注释信息author,date,description

打开setting设置窗口 file and code Templates 2、编辑Class模版 /*** Author:${USER}* Date:${YEAR}-${MONTH}-${DAY}* Description:TODO* */ 创建一个新JAVA类&#xff0c;测试一下&#xff0c;OK

chatgpt赋能python:如何通过Python赚取外快:SEO技巧分享

如何通过Python赚取外快&#xff1a;SEO技巧分享 作为一名有10年Python编程经验的工程师&#xff0c;我发现Python不仅用来写代码&#xff0c;还可以用来赚取外快。SEO是一个非常赚钱的市场&#xff0c;而Python可以帮助我们更好地优化网站&#xff0c;从而实现更高的排名&…

一步一步学OAK之四:实现如何在低延迟下使用高分辨率视频

目录 Setup 1: 创建文件Setup 2: 安装依赖Setup 3: 导入需要的包Setup 4: 创建pipelineSetup 5: 创建节点Setup 6: 设置节点的属性和参数。Setup 7: 建立链接关系Setup 8: 连接设备并启动管道Setup 9: 创建与DepthAI设备通信的输入队列和输出队列Setup 10: 主循环获取视频帧显示…

深度学习与神经网络阅读笔记(持续更新)

深度学习与神经网络阅读笔记&#xff08;持续更新&#xff09; 机器学习基础绪论人工智能主要领域可分为如下&#xff1a;人工智能的发展史&#xff1a;机器学习表示学习深度学习 线性模型Logistic回归Softmax回归感知器支持向量机总结对比 基础模型循环神经网络应用到机器学习…

MongoTemplate手动动态创建(简版)

1、背景 最近遇到一个需求&#xff0c;就是动态获取springboot中MongoTemplate&#xff0c;有哪些mongo数据库在项目启动的时候不确定&#xff0c;运行过程中有可能会增加&#xff0c;也有可能减少。只能通过一个接口获取所有mongo数据库的地址。但是springboot本身提供的mong…

panda3d 模型转换命令复习学习

在此学习了把maya模型转换为panda3d的egg格式&#xff1b; 在Panda3d中转换Maya模型为egg格式并使用pview查看_panda3d egg文件浏览器_bcbobo21cn的博客-CSDN博客 下面继续看一下模型转换命令&#xff1b;列出带 egg 字符串的命令&#xff1b; 先复习一下&#xff0c;可以把m…

Java -- XXL-JOB分布式任务调度平台

XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用 xxl是xxl-job的开发者大众点评的【许雪里】名称的拼音开头 官网地址 分布式任务调度平台XXL-JOB 文档地址…

响应数据加密解决方案

需求分析 响应数据加密是一种很重要的安全措施,可以保护数据在传输过程中不被未经授权的用户拦截、窃取或篡改。以下是响应数据加密需求分析: 响应数据必须进行加密: 所有响应数据必须进行加密,以保证数据在传输过程中的安全性。服务器可以采用HTTPS协议对响应数据进行加密…

剑指 Offer 46: 把数字翻译成字符串

这道题先画模型 假设3个数&#xff0c;第一个第二个可以组&#xff0c;第二个第三个可以组。所以有3种 123 && 字母3 && 1字母 当发现有两种操作方法&#xff0c;说明当前方法出错误了&#xff0c;必须立即想别的办法&#xff01; 除了使用一直除外&#xff…

ad18报错:net antennae:track

画了板子之后发现有这个错误提示&#xff0c;看了图&#xff0c;发现是在一个焊盘下面有2根残留的线&#xff0c;而且线边上出现了天线标志 net antennae的含义是网络天线&#xff0c;这里可以理解为板卡上某个网络的布线形成了天线&#xff0c;但是没有特别标注这一部分是天线…

【Mysql】MySQL体系结构,InnoDB、MyISAM存储引擎,索引结构、分类、语法、性能分析

1. MySQL体系结构 连接层 主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念&#xff0c;为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 服务层…

(五)Web_Server+网页可视化展示

第一步&#xff1a;先使用nodeJS获取mqtt转发的数据&#xff1a;添加链接描述 第二步&#xff1a;使用fs库&#xff0c;将数据存入txt文件(接上一步,这里没处理数据格式&#xff0c;只是测试) var fsrequire("fs");const mqtt require(mqtt) //存储订阅的消息 var …

Android ConstrainLayout布局中View位置的介绍与使用

一、介绍 ConstrainLayout是一款布局View&#xff0c;再Design库中&#xff0c;现已被大家广泛接受并使用。ConstrainLayout的布局采用的方式和其他都不同&#xff0c;他的对其方式是类似RelativeLayout&#xff0c;但是和RelativeLayout有明显的区别。 在布局渲染的时候&#…

获取Xilinx FPGA芯片IDCODE的4种方法(支持任何FPGA型号)

文章目录 方式1&#xff1a;官方文档方式2&#xff1a;一个头文件方式3&#xff1a;BSDL文件方法4&#xff1a;芯片IDCODE在线搜索网站Xilinx FPGA部分型号IDCODE汇总 方式1&#xff1a;官方文档 对于常用的Spartan-6系列可以在UG380文档中找到对应的IDCODE&#xff0c;Sparta…

CM+CDH 构建企业大数据平台

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

电磁阀位、通、开/闭原理精髓

一、引用 电磁阀在液/气路系统中&#xff0c;用来实现液路的通断或液流方向的改变&#xff0c;它一般具有一个可以在线圈电磁力驱动下滑动的阀芯&#xff0c;阀芯在不同的位置时&#xff0c;电磁阀的通路也就不同。 阀芯在线圈不通电时处在甲位置&#xff0c;在线圈通电时处在…

ChatGPT助力校招----面试问题分享(八)

1 ChatGPT每日一题&#xff1a;有源和无源滤波器 问题&#xff1a;有源和无源滤波器的区别 ChatGPT&#xff1a;有源滤波器和无源滤波器是指使用不同的电路元件来实现滤波功能的电路 有源滤波器使用了一个或多个有源元件&#xff0c;例如晶体管、运算放大器等&#xff0c;以…

浅浅总结一下雅思听力技巧

1. 地图题 读题步骤要明确 &#xff08;1&#xff09;看图&#xff0c;要看看题目中是否有东南西北的标志&#xff0c;如果有的话&#xff0c;那么大概率题目中就会用到。同时也标记好左右的标志&#xff0c;防止考试的时候太紧张分不清。 弄清楚个元素的相对位置&#xff0…

华为OD机试真题 Python 实现【开心消消乐】【2023 B卷 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、Python算法源码五、效果展示1、输入2、输出3、说明 一、题目描述 给定一个N行M列的二维矩阵&#xff0c;矩阵中每个位置的数字取值为0或1。矩阵示例如&#xff1a; 1 1 0 0 0 0 0 1 0 0 1 1 1 1 1 1 现需要将矩阵中所有的1进行…