返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java RSA加解密算法学习
  • 449
分享到

Java RSA加解密算法学习

java算法学习RSA非对称加密 2023-10-27 15:10:15 449人浏览 泡泡鱼
摘要

一、前言 1.1 问题思考 为什么需要加密 / 解密?信息泄露可能造成什么影响? 二、 基础回顾 2.1 加密技术 加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目

一、前言

1.1 问题思考

  1. 为什么需要加密 / 解密?
  2. 信息泄露可能造成什么影响?

二、 基础回顾

2.1 加密技术

加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目的地后再用相同或不同的手段还原(解密)。

加密技术包括两个元素:算法和密钥。算法是将普通的信息或者可以理解的信息与一串数字(密钥)结合,产生不可理解的密文的步骤,密钥是用来对数据进行编码和解密的一种算法。在安全保密中,可通过适当的钥加密技术和管理机制来保证网络的信息通信安全。简言之:

  • 算法:加密 / 解密所使用的转换规则
  • 密钥:加密 / 解密所使用的指令或代码
    在这里插入图片描述

2.2 加密的目的与方式

加密目的:就是为了保护数据在存储状态下和在传输过程中,不被窃取、解读和利用。简单的说:确保数据的机密性和保护信息的完整性;
加密的方式:包括单向散列加密、对称加密、非对称加密三种。

2.3 加密方式简述

方式一:单向散列加密

根据输入长度信息进行散列计算,得到固定长度输出,常用于密码保存,常见的是MD5,SHA等,通常会加盐处理;
在这里插入图片描述
特点: 加密效率高、单方向加密
安全性:不安全(相对于对称加密)
使用情况:比较主流的加密方式

方式二:对称加密

采用单钥密码系统加密方法,同一个密钥可以同时用作信息的加密和解密。常见有AES
在这里插入图片描述
特点:加密效率高、双方使用的密钥相同
安全性:不安全(相对于非对称加密)
使用情况:比较主流的加密方式

方式三:非对称加密

加密和解密使用的是不同的秘钥,其中一个对外公开,称为公钥,另一个被称为私钥。若使用公钥对数据进行加密,则只有使用对应的私钥才能解密,反之亦然。常见的有RSA。
在这里插入图片描述
关于密钥

  • 公钥:任何人都可以持有,一般用于加密作用
  • 私钥:只有自己持有,一般用于数字签名,签名的数据,可以证明是私钥持有人发送的数据,私钥签名的数据,私钥持有人无法否认自己发送这个消息

特点

  1. 公钥加密的只有对应的私钥能解开
  2. 加密解密效率很低,一般不做大量数据加解密使用

安全性较高,使用的时候,一般配合对称机密使用,建立之初先使用非对称加密,协商好对称加密的算法和密钥,然后使用对称加密,进行后续加解密。

比如:使用对称加密加密很大的数据,非对称加密可以加密对称加密的密钥,报文一起传输,这样既保证了安全性,又保证了加密效率。

三、RSA加密实践

3.1 RSA 加解密工具

import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;import java.security.*;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;public class RSAUtil01 {        private static final String RSA_KEY_ALGoRITHM = "RSA";        private static final String SIGNATURE_ALGORITHM = "MD5withRSA";        private static final String PUBLIC_KEY = "RSAPublicKey";        private static final String PRIVATE_KEY = "RSAPrivateKey";        private static final int KEY_SIZE = 1024;        private static Map<String, String> iniTKEy() throws Exception {        KeyPairGenerator keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);        SecureRandom secrand = new SecureRandom();                secrand.setSeed("initSeed".getBytes());                keygen.initialize(KEY_SIZE, secrand);        KeyPair keys = keygen.genKeyPair();        // 获取公钥        byte[] pub_key = keys.getPublic().getEncoded();        String publicKeyString = Base64.encodeBase64String(pub_key);        // 获取私钥        byte[] pri_key = keys.getPrivate().getEncoded();        String privateKeyString = Base64.encodeBase64String(pri_key);        Map<String, String> keyPairMap = new HashMap<>();        keyPairMap.put(PUBLIC_KEY, publicKeyString);        keyPairMap.put(PRIVATE_KEY, privateKeyString);        return keyPairMap;    }        public static String encodeBase64String(byte[] key) {        return Base64.encodeBase64String(key);    }        public static byte[] decodeBase64(String key) {        return Base64.decodeBase64(key);    }        public static String encryptByPubKey(String data, String publicKey) throws Exception {        byte[] pubKey = RSAUtil01.decodeBase64(publicKey);        byte[] enSign = encryptByPubKey(data.getBytes(), pubKey);        return Base64.encodeBase64String(enSign);    }        public static byte[] encryptByPubKey(byte[] data, byte[] pubKey) throws Exception {        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.ENCRYPT_MODE, publicKey);        return cipher.doFinal(data);    }        public static String encryptByPriKey(String text, String privateKey) {        try {            byte[] priKey = RSAUtil01.decodeBase64(privateKey);            byte[] enSign = encryptByPriKey(text.getBytes(), priKey);            return Base64.encodeBase64String(enSign);        } catch (Exception e) {            throw new RuntimeException("加密字符串[" + text + "]时遇到异常", e);        }    }        public static byte[] encryptByPriKey(byte[] data, byte[] priKey) throws Exception {        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.ENCRYPT_MODE, privateKey);        return cipher.doFinal(data);    }        public static byte[] decryptByPubKey(byte[] data, byte[] pubKey) throws Exception {        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.DECRYPT_MODE, publicKey);        return cipher.doFinal(data);    }        public static String decryptByPubKey(String data, String publicKey) throws Exception {        byte[] pubKey = RSAUtil01.decodeBase64(publicKey);        byte[] design = decryptByPubKey(Base64.decodeBase64(data), pubKey);        return new String(design);    }        public static byte[] decryptByPriKey(byte[] data, byte[] priKey) throws Exception {        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.DECRYPT_MODE, privateKey);        return cipher.doFinal(data);    }        public static String decryptByPriKey(String secretText, String privateKey) {        try {            byte[] priKey = RSAUtil01.decodeBase64(privateKey);            byte[] design = decryptByPriKey(Base64.decodeBase64(secretText), priKey);            return new String(design);        } catch (Exception e) {            throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e);        }    }        public static String sign(byte[] data, byte[] priKey) throws Exception {        // 取得私钥        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        // 生成私钥        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);        // 实例化Signature        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        // 初始化Signature        signature.initSign(privateKey);        // 更新        signature.update(data);        return Base64.encodeBase64String(signature.sign());    }        public boolean verify(byte[] data, byte[] sign, byte[] pubKey) throws Exception {        // 实例化密钥工厂        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);        // 初始化公钥        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);        // 产生公钥        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);        // 实例化Signature        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        // 初始化Signature        signature.initVerify(publicKey);        // 更新        signature.update(data);        // 验证        return signature.verify(sign);    }    public static void main(String[] args) {        try {            Map<String, String> keyMap = initKey();            String publicKeyString = keyMap.get(PUBLIC_KEY);            String privateKeyString = keyMap.get(PRIVATE_KEY);            System.out.println("公钥:" + publicKeyString);            System.out.println("length: " + publicKeyString.length());            System.out.println("私钥:" + privateKeyString);            System.out.println("length: " + privateKeyString.length());            // 待加密数据            String data = "admin123";            // 公钥加密            String encrypt = RSAUtil01.encryptByPubKey(data, publicKeyString);            // 私钥解密            String decrypt = RSAUtil01.decryptByPriKey(encrypt, privateKeyString);            System.out.println("加密前:" + data);            System.out.println("明文length:" + data.length());            System.out.println("加密后:" + encrypt);            System.out.println("解密后:" + decrypt);        } catch (Exception e) {            e.printStackTrace();        }    }}

如图所示, 生成一对1024 bit 的 RSA 密钥对,并加解密成功。
在这里插入图片描述

3.2 深入实践案例探索

案例一:报文长度过长加解密失败

测试发现当明文过长时,加密异常,返回如下报错
在这里插入图片描述
原因分析: RSA 加解密时,对加密的数据大小有限制,最大不大于密钥长度。

在使用 1024 位的密钥时,最大可以加密 1024/8 = 128字节的数据,此时需要对数据进行分组加密,分组加密后的加密串拼接成一个字符串返回给客户端。如果 Padding 方式使用默认的 OPENSSL_PKCS1_PADDING(需要占用11字节用于填充),则明文长度最多为 128 - 11 = 117 Bytes。

同理,当解密的密文超过128Byte时,也需要进行分组解密

案例二:分段加解密的的实现

实现代码:

public static String encrypt(String plainText, String publicKeyStr) throws Exception {        System.out.println("明文lenth为"+plainText.length());        byte[] plainTextArray = plainText.getBytes();        PublicKey publicKey = getPublicKey(publicKeyStr);        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);        cipher.init(Cipher.ENCRYPT_MODE, publicKey);        int inputLen = plainTextArray.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        int i = 0;        byte[] cache;        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {                cache = cipher.doFinal(plainTextArray, offSet, MAX_ENCRYPT_BLOCK);            } else {                cache = cipher.doFinal(plainTextArray, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_ENCRYPT_BLOCK;        }        byte[] encryptText = out.toByteArray();        out.close();        return Base64.getEncoder().encodeToString(encryptText);    }        public static String decrypt(String encryptTextHex, String privateKeyStr) throws Exception{        byte[] encryptText = Base64.getDecoder().decode(encryptTextHex);        PrivateKey privateKey = getPrivateKey(privateKeyStr);        Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);        cipher.init(Cipher.DECRYPT_MODE, privateKey);        int inputLen = encryptText.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        // 对数据分段解密        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {                cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK);            } else {                cache = cipher.doFinal(encryptText, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_DECRYPT_BLOCK;        }        byte[] plainText = out.toByteArray();        out.close();        return new String(plainText);}

案例三:当密钥长度非默认的1024,改为2048bit时,如何生成密钥、如何分段

如上文提到, 当密钥对改为 2048 位时, 最大加密明文大小 = 2048(bit) / 8 - 11(byte) = 245 byte

private static final int MAX_ENCRYPT_BLOCK = 245;    private static final int MAX_DECRYPT_BLOCK = 256;  public static Map<String, Object> initKey() throws Exception {        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);        //设置密钥对的bit数 越大越安全        keyPairGen.initialize(2048);        KeyPair keyPair = keyPairGen.generateKeyPair();        //获取公钥        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();        //获取私钥        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();        Map<String, Object> keyMap = new HashMap(2);        keyMap.put(PUBLIC_KEY, publicKey);        keyMap.put(PRIVATE_KEY, privateKey);        return keyMap;}

四、总结

4.1 核心点简述

  1. RSA加密默认密钥长度是1024,但是密钥长度必须是64的倍数,在512到65536位之间即可。
  2. RSA加密数据有长度限制,如果加密数据太长(大于密钥长度)会报错,此时的解决方案是 可以分段加密。
  3. RSA如果采用分段加密,当密钥对改为2048位时,RSA最大加解密文大小也需要调整:
    • RSA密钥长度=1024时, 最大加密明文长度是117,解密明文长度是128;
    • RSA密钥长度=2048时, 最大加密明文长度是245,解密明文长度是256;

4.2 PKCS1 和 PKCS8 的区别

PKCS#1格式以-----BEGIN RSA PRIVATE KEY-----开头以-----END RSA PRIVATE KEY-----结束PKCS#8格式以-----BEGIN PRIVATE KEY-----开头以-----END PRIVATE KEY-----结束

通常JAVA中需要PKCS8 格式的密钥,在线 RSA 加解密网站:https://www.toolscat.com/decode/rsa 有助于提效。

来源地址:https://blog.csdn.net/qq_41893274/article/details/130120395

--结束END--

本文标题: Java RSA加解密算法学习

本文链接: https://lsjlt.com/news/496042.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java RSA加解密算法学习
    一、前言 1.1 问题思考 为什么需要加密 / 解密?信息泄露可能造成什么影响? 二、 基础回顾 2.1 加密技术 加密技术是最常用的安全保密手段,利用技术手段把重要的数据变为乱码(加密)传送,到达目...
    99+
    2023-10-27
    java 算法 学习 RSA 非对称加密
  • python实现RSA加密(解密)算法
    RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击...
    99+
    2022-06-04
    算法 python RSA
  • 如何理解加密算法RSA
    本篇内容介绍了“如何理解加密算法RSA”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!RSA加密我们需要先预...
    99+
    2024-04-02
  • Java 实现RSA非对称加密算法
    目录  公钥与私钥  Java实现  公钥与私钥   公钥与私钥是成对的,一般的,我们认为的是公钥加密、私钥解密、私钥签名、公钥验证,有人说成私钥加密,公钥解密时不对的。   公钥与...
    99+
    2024-04-02
  • JAVA 如何实现解密RSA算法并使用JS加密
    JAVA 如何实现解密RSA算法并使用JS加密?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。JAVA 中解密RSA算法JS加密实例详解有这样一个需求,前端登录的用户名密码,...
    99+
    2023-05-31
    java js加密 rsa算法
  • 详解RSA加密算法的原理与Java实现
    目录对称加密和非对称加密RSA加密是什么RSA的加密过程前几天阿粉刚刚说了这个 MD5 加密的前世今生,因为 MD5 也确实用的人不是很多了,阿粉就不再继续的一一赘述了,今天阿粉想给...
    99+
    2022-11-13
    Java RSA加密算法 Java RSA加密 Java RSA
  • RSA加密/解密
    一、RSA加密/解密在线教程 1.1、RSA算法介绍 RSA加密算法是一种可逆的非对称加密算法,即RSA加密时候用的密钥(公钥)和RSA解密时用的密钥(私钥)不是同一把。基本原理是将两个很大的质数相乘很容易得到乘积,但是该乘积分解质因数却很...
    99+
    2023-08-31
    安全 算法 网络安全 服务器 网络
  • python3中rsa加密算法详情
    前言: rsa加密,是一种加密算法,目前而言,加密算法,是对数据、密码等进行加密。第一次接触rsa加密算法是linux中免密登陆设置,当时一直以为密钥加密是像token一样的,直到现...
    99+
    2024-04-02
  • python----RSA非对称加密算法
    最近在搞项目的接口持续性自动化测试,好久没有更新博客了。 项目中接触到很多加密相关的数据,很多项目都会用到非对称加密算法来保证前端和服务器交互的数据安全。 下面介绍下python下怎么使用RSA加密算法: import rsa (pub...
    99+
    2023-01-31
    加密算法 非对称 python
  • Flutter RSA加密解密的方法
    本文小编为大家详细介绍“Flutter RSA加密解密的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“Flutter RSA加密解密的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。数...
    99+
    2023-06-30
  • 如何在java中使用RSA算法对密码进行加密与解密
    本篇文章给大家分享的是有关如何在java中使用RSA算法对密码进行加密与解密,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。前言:  RSA是第一个比较完善的公开密钥算...
    99+
    2023-05-31
    java rsa算法 ava
  • python rsa 加密解密
    最近有需求,需要研究一下RSA加密解密安全;在网上百度了一下例子文章,很少有文章介绍怎么保存、传输、打印加密后的文本信息,都是千篇一律的。直接在一个脚本,加密后的文本信息赋于变量,然后立马调用解密。仔细想了...
    99+
    2022-06-04
    加密解密 python rsa
  • Python RSA加密解密
    一、RSA加密算法 RSA加密算法是一种非对称加密算法,加密的秘钥是由公钥和私钥两部分组成秘钥对,公钥用来加密消息,私钥用来解密消息,公钥是公开的,给对方进行加密,私钥则是用户自己保留,用来对加密的数...
    99+
    2023-09-03
    python RSA 加密 解密
  • RSA加密算法的简单案例
    RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码***。那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例。在使用数据集进行身份认证时,密码存在数据库中,认...
    99+
    2024-04-02
  • 教你用Java实现RSA非对称加密算法
    目录一、非对称加密二、RSA算法三、RSA算法Java语言实现一、非对称加密 非对称加密算法是一种密钥的保密方法。 非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥...
    99+
    2024-04-02
  • RSA加密算法如何在java项目中实现
    这篇文章将为大家详细讲解有关RSA加密算法如何在java项目中实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、什么是非对称加密加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加...
    99+
    2023-05-31
    java rsa加密 ava
  • C++实现RSA加密解密算法是示例代码
    目录一、什么是RSA算法1.对称加密2.非对称加密3.非对称加密的应用二、RSA算法的基础操作步骤1.生成公钥和私钥2.用公钥加密信息 3.用私钥解密信息三、AC代码四、R...
    99+
    2024-04-02
  • 详解PHP使用非对称加密算法RSA
    目录加密的类型非对称加密算法具体实现1、加密解密的第一步2、PHP的加密解密类库调用demo加密的类型 在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明...
    99+
    2024-04-02
  • Thinkphp 6 使用RSA非对称加密算法 对接口加密解密
    后台接口中 经常使用到加密算法 如何使用RSA 非对称加密 对数据进行加密传输 下载RSA 加密算法 php-Rsa算法下载 将下载好的RSA 算法 放入 到 TP6项目根目录下 exten...
    99+
    2023-09-17
    php 算法
  • python密码学RSA密码加密教程
    目录加密算法模块 哈希值初始化函数algorithm加密程序的完整代码在本章中,我们将重点介绍RSA密码加密的不同实现及其所涉及的功能.您可以引用或包含此python文件以...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作