使用 Java 原生或 Hutool 工具包编写非对称加解密的工具类

1、什么是非对称加密

使用一对(2个)密钥:一个用于加密信息,另一个则用于解密信息。有“公钥(Public Key)”和“私钥(Private Key)”之分。

非对称加密的“公钥”和“私钥”是成对出现(就像“梁山伯”与“祝英台”一样,世界上独一无二的一对),需要使用工具一起同时生成。但是通过公钥推算不出私钥是什么,同样的,通过私钥也推算不出公钥长什么样(“梁山伯”丢失了那“祝英台”也失去意义)。

按照密钥依据性质划分,将其中的一个向外界公开,称为公钥;另一个则自己保留,称为私钥。

大多数情况下,公钥(Public key)用于数据加密,私钥(Private key)用于数据解密。但是并不是绝对的。也就是说:可以使用公钥加密数据,然后使用私钥解密数据。也可以使用私钥加密数据,然后使用公钥解密数据

但是:

1、私钥加密的数据,只能对应的公钥才能解密出来,私钥自己无法解密

2、公钥加密的数据,也是只有对应的私钥才能解密出来,公钥自己也无法解密。

2、使用 Java 原生编写非对称加解密工具类

package com.study.util;

import java.security.*;
import javax.crypto.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * @author CSDN 流放深圳
 * @description Java原生的非对称加密工具类
 * @create 2024-04-13 12:30
 * @since 1.0.0
 */
public class NativeSecurityUtil {

    /**
     * 生成一对公钥&私钥(仅供测试使用,实际应用上只能生成一次,然后把公钥和私钥保存下来。切忌在业务中每次都调用此方法,否则造成秘钥丢失,数据不可解密!!!)
     * @return
     */
    public static Map<String, String> generateKey() {
        Map<String, String> map = new HashMap<>();
        try{
            // 生成密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024); // 设置密钥长度为 1024 位
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicObj = keyPair.getPublic();
            PrivateKey privateObj = keyPair.getPrivate();
            String publicKey = Base64.getEncoder().encodeToString(publicObj.getEncoded());
            String privateKey = Base64.getEncoder().encodeToString(privateObj.getEncoded());
            map.put("publicKey", publicKey);
            map.put("privateKey", privateKey);
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }


    /****************************** 【方式一:私钥加密 & 公钥解密】  ***********************************************/
    /**
     * 【方式一】私钥加密
     *
     * @param str        待加密字符串
     * @param privateKey 私钥
     * @return
     */
    public static String encryptByPrivateKey(String str, String privateKey) {
        String result = null;
        try{
            byte[] encoded = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateObj = keyFactory.generatePrivate(privateKeySpec);
            Cipher cipherForEncryption = Cipher.getInstance("RSA");
            cipherForEncryption.init(Cipher.ENCRYPT_MODE, privateObj);

            //要加密的字符串转为 byte 类型
            byte[] originalBytes = str.getBytes("UTF-8");
            byte[] encryptedBytes = cipherForEncryption.doFinal(originalBytes);
            result = Base64.getEncoder().encodeToString(encryptedBytes);
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 【方式一】公钥解密
     *
     * @param str       待解密字符串
     * @param publicKey 公钥
     * @return
     */
    public static String decryptByPublicKey(String str, String publicKey) {
        String result = null;
        try{
            byte[] encoded = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicObj = keyFactory.generatePublic(publicKeySpec);
            Cipher cipherForDecryption = Cipher.getInstance("RSA");
            cipherForDecryption.init(Cipher.DECRYPT_MODE, publicObj);
            byte[] decryptedBytes = cipherForDecryption.doFinal(Base64.getDecoder().decode(str));
            result = new String(decryptedBytes, "UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }


    /****************************** 【方式二:公钥加密 & 私钥解密】  ***********************************************/
    /**
     * 【方式二】公钥加密
     * @param str
     * @param publicKey
     * @return
     */
    public static String encryptByPublicKey(String str, String publicKey) {
        String result = null;
        try{
            byte[] encoded = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicObj = keyFactory.generatePublic(publicKeySpec);
            Cipher cipherForEncryption = Cipher.getInstance("RSA");
            cipherForEncryption.init(Cipher.ENCRYPT_MODE, publicObj);

            //要加密的字符串转为 byte 类型
            byte[] originalBytes = str.getBytes("UTF-8");
            byte[] encryptedBytes = cipherForEncryption.doFinal(originalBytes);
            result = Base64.getEncoder().encodeToString(encryptedBytes);
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 【方式二】私钥解密
     * @param str
     * @param privateKey
     * @return
     */
    public static String decryptByPrivateKey(String str, String privateKey) {
        String result = null;
        try{
            byte[] encoded = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encoded);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateObj = keyFactory.generatePrivate(privateKeySpec);
            Cipher cipherForDecryption = Cipher.getInstance("RSA");
            cipherForDecryption.init(Cipher.DECRYPT_MODE, privateObj);
            byte[] decryptedBytes = cipherForDecryption.doFinal(Base64.getDecoder().decode(str));
            result = new String(decryptedBytes, "UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        //首先生成一对公钥&私钥,记得保存下来
        Map<String, String> map = generateKey();
        String privateKey = map.get("privateKey");
        String publicKey = map.get("publicKey");
        System.out.println("私钥 privateKey=" + privateKey);
        System.out.println("公钥 publicKey=" + publicKey);

        String str = "CSDN流放深圳666";
        System.out.println("测试字符串=" + str);

        System.out.println("*********************** 【方式一:私钥加密 & 公钥解密】 *************************");
        String encrypt = encryptByPrivateKey(str, privateKey);
        System.out.println("【方式一】私钥加密结果 encrypt=" + encrypt);

        String decrypt = decryptByPublicKey(encrypt, publicKey);
        System.out.println("【方式一】公钥解密结果 decrypt=" + decrypt);

        System.out.println("*********************** 【方式二:公钥加密 & 私钥解密】 *************************");
        String encrypt222 = encryptByPublicKey(str, publicKey);
        System.out.println("【方式二】公钥加密结果 encrypt222=" + encrypt222);

        String decrypt222 = decryptByPrivateKey(encrypt222, privateKey);
        System.out.println("【方式二】私钥解密结果 decrypt222=" + decrypt222);

    }
}

测试结果:

私钥 privateKey=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJd【因数据太长,省略掉后面的结果】
公钥 publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5b【因数据太长,省略掉后面的结果】
测试字符串=CSDN流放深圳666
*********************** 【方式一:私钥加密 & 公钥解密】 *************************
【方式一】私钥加密结果 encrypt=Zx5loAwOM2C2mxHz8Yz/rn0e9+/y/9OX【因数据太长,省略掉后面的结果】
【方式一】公钥解密结果 decrypt=CSDN流放深圳666
*********************** 【方式二:公钥加密 & 私钥解密】 *************************
【方式二】公钥加密结果 encrypt222=H7dL/HArwa7QqXT8+hi25pC69w【因数据太长,省略掉后面的结果】
【方式二】私钥解密结果 decrypt222=CSDN流放深圳666

3、使用 Hutool 工具包编写非对称加解密工具类

这里演示的是 hutool 最新工具包 5.8.27(2024年4月13日)的工具类。hutool 工具包有很多组件,可以查看官网:https://hutool.cn/docs/#/?id=%f0%9f%93%9a%e7%ae%80%e4%bb%8b

模块介绍
hutool-aopJDK动态代理封装,提供非IOC下的切面支持
hutool-bloomFilter布隆过滤,提供一些Hash算法的布隆过滤
hutool-cache简单缓存实现
hutool-core核心,包括Bean操作、日期、各种Util等
hutool-cron定时任务模块,提供类Crontab表达式的定时任务
hutool-crypto加密解密模块,提供对称、非对称和摘要算法封装
hutool-dbJDBC封装后的数据操作,基于ActiveRecord思想
hutool-dfa基于DFA模型的多关键字查找
hutool-extra扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等)
hutool-http基于HttpUrlConnection的Http客户端封装
hutool-log自动识别日志实现的日志门面
hutool-script脚本执行封装,例如Javascript
hutool-setting功能更强大的Setting配置文件和Properties封装
hutool-system系统参数调用封装(JVM信息等)
hutool-jsonJSON实现
hutool-captcha图片验证码实现
hutool-poi针对POI中Excel和Word的封装
hutool-socket基于Java的NIO和AIO的Socket封装
hutool-jwtJSON Web Token (JWT)封装实现

可以根据需求对每个模块单独引入,也可以通过引入 hutool-all 方式引入所有模块。 

pom.xml 依赖

        <!-- hutool 加解密工具包 https://mvnrepository.com/artifact/cn.hutool/hutool-crypto -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-crypto</artifactId>
            <version>5.8.27</version>
        </dependency>

代码示例:

package com.study.util;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;

import java.util.HashMap;
import java.util.Map;

/**
 * @author CSDN 流放深圳
 * @description Hutool 非对称加解密工具类
 * @create 2024-04-13 12:50
 * 参考链接:https://hutool.cn/docs/#/crypto/非对称加密-AsymmetricCrypto?id=%e4%bb%8b%e7%bb%8d
 * @since 1.0.0
 */
public class HutoolSecurityUtil {

    /****************************** 【方式一:私钥加密 & 公钥解密】  ***********************************************/
    /**
     * 【方式一】私钥加密
     *
     * @param str        待加密字符串
     * @param privateKey 私钥
     * @return
     */
    public static String encryptByPrivateKey(String str, String privateKey) {
        if (StrUtil.isEmpty(str)) return null;
        RSA rsa = new RSA(privateKey, null);
        return rsa.encryptBase64(str, KeyType.PrivateKey);
    }

    /**
     * 【方式一】公钥解密
     *
     * @param str       待解密字符串
     * @param publicKey 公钥
     * @return
     */
    public static String decryptByPublicKey(String str, String publicKey) {
        if (StrUtil.isEmpty(str)) return null;
        RSA rsa = new RSA(null, publicKey);
        byte[] decrypt = rsa.decrypt(str, KeyType.PublicKey);
        return StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
    }


    /****************************** 【方式二:公钥加密 & 私钥解密】  ***********************************************/
    /**
     * 【方式二】公钥加密
     * @param str
     * @param publicKey
     * @return
     */
    public static String encryptByPublicKey(String str, String publicKey) {
        if (StrUtil.isEmpty(str)) return null;
        RSA rsa = new RSA(null, publicKey);
        return rsa.encryptBase64(str, KeyType.PublicKey);
    }

    /**
     * 【方式二】私钥解密
     * @param str
     * @param privateKey
     * @return
     */
    public static String decryptByPrivateKey(String str, String privateKey) {
        if (StrUtil.isEmpty(str)) return null;
        RSA rsa = new RSA(privateKey, null);
        byte[] decrypt = rsa.decrypt(str, KeyType.PrivateKey);
        return StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
    }



    /**
     * 测试
     *
     * @param args
     */
    public static void main(String[] args) {
        //首先生成一对公钥&私钥,记得保存下来
        Map<String, String> map = generateKey();
        String privateKey = map.get("privateKey");
        String publicKey = map.get("publicKey");
        System.out.println("私钥 privateKey=" + privateKey);
        System.out.println("公钥 publicKey=" + publicKey);

        String str = "让天下没有难写的代码 Come on baby!";
        System.out.println("测试字符串=" + str);

        System.out.println("*********************** 【方式一:私钥加密 & 公钥解密】 *************************");
        String encrypt = encryptByPrivateKey(str, privateKey);
        System.out.println("【方式一】私钥加密结果 encrypt=" + encrypt);

        String decrypt = decryptByPublicKey(encrypt, publicKey);
        System.out.println("【方式一】公钥解密结果 decrypt=" + decrypt);

        System.out.println("*********************** 【方式二:公钥加密 & 私钥解密】 *************************");
        String encrypt222 = encryptByPublicKey(str, publicKey);
        System.out.println("【方式二】公钥加密结果 encrypt222=" + encrypt222);

        String decrypt222 = decryptByPrivateKey(encrypt222, privateKey);
        System.out.println("【方式二】私钥解密结果 decrypt222=" + decrypt222);


    }

    /**
     * 生成一对公钥&私钥(仅供测试使用,实际应用上只能生成一次,然后把公钥和私钥保存下来。切忌在业务中每次都调用此方法,否则造成秘钥丢失,数据不可解密!!!)
     */
    public static Map<String, String> generateKey() {
        Map<String, String> map = new HashMap<>();
        RSA rsa = new RSA();
        String privateKey = rsa.getPrivateKeyBase64();//获得私钥
        String publicKey = rsa.getPublicKeyBase64();//获得公钥
        map.put("privateKey", privateKey);
        map.put("publicKey", publicKey);
        return map;
    }

}

测试结果:

私钥 privateKey=MIICdQIBADANBgkqhkiG9w【因数据太长,省略掉后面的结果】
公钥 publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GN【因数据太长,省略掉后面的结果】
测试字符串=让天下没有难写的代码 Come on baby!
*********************** 【方式一:私钥加密 & 公钥解密】 *************************
【方式一】私钥加密结果 encrypt=khpoO4WQbo3TDW3+WUo【因数据太长,省略掉后面的结果】
【方式一】公钥解密结果 decrypt=让天下没有难写的代码 Come on baby!
*********************** 【方式二:公钥加密 & 私钥解密】 *************************
【方式二】公钥加密结果 encrypt222=TrXA7AjAchNwUPfIx7【因数据太长,省略掉后面的结果】
【方式二】私钥解密结果 decrypt222=让天下没有难写的代码 Come on baby!

需要注意的是,使用工具类生成一对公钥和私钥后,需要保存起来,且私钥不能对外泄露,否则后续找不到,直接导致之前的数据无法加解密。

—  end —

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java 中文官方教程 2022 版(四十九)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html JAXB 示例 原文&#xff1a;docs.oracle.com/javase/tutorial/jaxb/intro/examples.html 以下部分描述如何使用包含在 JAXB RI 捆绑包中的示例应用程序。JAXB RI 捆绑包可从jaxb.java.net获取。下载并安装…

基于OptiTrack跟踪系统和Turtlebot机器人的视觉SLAM定位评估

本文旨在介绍使用OptiTrack光学跟踪系统和Turtlebot机器人进行视觉SLAM定位实验的详细流程&#xff0c;包括实验平台搭建过程、数据处理过程以及SLAM估计评估方法。由于涉及知识较多&#xff0c;部分内容只给出了相关参考博文链接。 1 实验平台搭建 实验平台包括OptiTrack光学…

使用 Meltano 将数据从 Snowflake 导入到 Elasticsearch:开发者之旅

作者&#xff1a;来自 Elastic Dmitrii Burlutskii 在 Elastic 的搜索团队中&#xff0c;我们一直在探索不同的 ETL 工具以及如何利用它们将数据传输到 Elasticsearch&#xff0c;并在传输的数据上实现 AI 助力搜索。今天&#xff0c;我想与大家分享我们与 Meltano 生态系统以及…

Python项目1 外星人入侵_记分

在本章中&#xff0c;我们将结束游戏《外星人入侵》的开发。我们将添加一个Play按钮&#xff0c;用于根据需要启动游戏以及在游戏结束后重启游戏。我们还将修改这个游戏&#xff0c;使其在玩 家的等级提高时加快节奏&#xff0c;并实现一个记分系统。阅读本章后&#xff0c;你将…

2024年【山东省安全员C证】考试资料及山东省安全员C证考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员C证考试资料考前必练&#xff01;安全生产模拟考试一点通每个月更新山东省安全员C证考试试题题目及答案&#xff01;多做几遍&#xff0c;其实通过山东省安全员C证作业模拟考试很简单。 1、【多选题】.设…

【计算机毕业设计】人事管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

二叉搜索树--搜索二维矩阵 II

题目描述 编写一个高效的算法来搜索 m * n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,…

Python之旅(一)——常量、变量、动态类型

文章目录 Python背景知识Python用途Python的优缺点Python前景&#xff08;钱景&#xff09; 常量和表达式变量与类型变量的定义变量命名的规则变量的使用变量的类型整数 int浮点数 float字符串布尔其他(暂不介绍&#xff09; 动态类型 标黄部分是和C语言不同的部分Python背景知…

在mysql中如何更新数据呢?

如何更新一条数据&#xff1f; 在 MySQL 中&#xff0c;更新一条数据可以使用 UPDATE 语句。以下是更新一条数据的基本语法&#xff1a; UPDATE table_name SET column1 value1, column2 value2,... WHERE condition;其中&#xff1a; table_name&#xff1a;要更新的表的…

Git以及Gitlab的快速使用文档

优质博文&#xff1a;IT-BLOG-CN 安装git 【1】Windows为例&#xff0c;去百度下载安装包。或者去官网下载。安装过秳返里略过&#xff0c;一直下一步即可。丌要忉记设置环境发量。 【2】打开cmd&#xff0c;输入git –version正确输出版本后则git安装成功。 配置ssh Git和s…

测试接口时出现HttpMessageNotReadableException: Required request body is missing

问题 测试接口时出现org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing异常 原因 发送请求时没有传参数 解决办法 第一种方式: 传个参数 第二种方式&#xff1a;给个空的JSON

常见的垃圾回收器(下)

文章目录 G1ShenandoahZGC 常见垃圾回收期&#xff08;上&#xff09; G1 参数1&#xff1a; -XX:UseG1GC 打开G1的开关&#xff0c;JDK9之后默认不需要打开 参数2&#xff1a;-XX:MaxGCPauseMillis毫秒值 最大暂停的时间 回收年代和算法 ● 年轻代老年代 ● 复制算法 优点…

Sam Altman新动向!被曝公开撬金主微软的客户!

Sam Altman向大公司们推销ChatGPT企业版&#xff0c;这其中包括一些微软的客户&#xff01; 好好好&#xff01; 你小子怎么回事&#xff01;金主的客户也不放过了是吧&#xff01; 根据路透社4月12日的报道&#xff0c;OpenAI首席执行官Sam Altman本月在旧金山、纽约和伦敦举…

HTML5+CSS3小实例:荧光图标悬停效果

实例:荧光图标悬停效果 技术栈:HTML+CSS 字体图标库:font-awesome 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=d…

【Qt 学习笔记】QWidget的windowOpacity属性 | cursor属性 | font属性

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的windowOpacity属性 | cursor属性 | font属性 文章编号&#…

抖音视频无水印采集拓客软件|视频批量下载提取工具

抖音视频无水印批量采集拓客软件助力高效营销&#xff01; 随着抖音平台的崛起&#xff0c;视频已成为各行各业进行营销的重要工具。但是&#xff0c;传统的视频下载方式往往效率低下&#xff0c;无法满足快速获取大量视频的需求。针对这一问题&#xff0c;我们开发了一款视频无…

Springboot+Vue项目-基于Java+MySQL的校园管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

基于公共转点的Alpha shapes有序边缘点提取

1、原理介绍 由Edelsbrunner H提出的alpha shapes算法是一种简单、有效的快速提取边界点算法。其克服了点云边界点形状影响的缺点,可快速准确提取边界点,其原理如下:对于任意形状的平面点云,若一个半径为a的圆,绕其进行滚动,其滚动的轨迹形成的点为轮廓点。需要注意的是,…

一文读懂Java中的WebEndpointProperties类(附Demo)

目录 前言1. 基本知识2. Demo3. 彩蛋 前言 对于Java的相关知识&#xff0c;推荐阅读&#xff1a;java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09; 1. 基本知识 Spring Boot 的配置类 WebEndpointProperties&#xff0c;用于配置 Web 端…

Flutter仿Boss-7.首页列表

效果 考察使用 Flutter Model的创建TabBar及TabBarView 的使用标签Wrap控件的使用列表ListView的使用 具体实现 今天懒的写文字了&#xff0c;想看具体实现的可以直接去我的github上&#xff1a; github&#xff1a;github.com/yixiaolunhui/flutter_project