Java加密实战:对称与非对称加密全解析
发布时间:2026/9/28 4:39:01来源:尧图网络
Java对称加密与非对称加密区别、用途及工具类实战教程更新时间是2025年12月2日, 具体时刻为9点53分4秒。作者是帆事靠自己。对称加密是一种对数据进行加密处理的技术手段, 它借助于唯一的一个密钥, 来同时搞定加密动作以及解密动作, 下面这篇长文所重点探讨的内容包括Java里的对称加密与非对称加密之间存在的各项区别、各自适用的具体场景、以及相关的工具类在实际开发中的运用方法等情况, 文章中是通过具体的代码示例来进行阐述说明的, 其详细程度相当之高, 因此那些需要知晓这些信息的朋友们不妨去浏览参考一下这个内容。前言在咱们做Java开发的过程中, 加密是保卫数据信息不被泄露的一个非常关键的核心方法。大家通常会把那些常用的加密手段分成两大类, 一种叫对称加密, 另一种呢, 则被称为非对称加密。有不少程序员朋友, 当它们刚刚起步接触这个领域的时候, 非常容易搞混这两者到底该怎么去用。所以在这篇文章里, 作者打算用最明白、最通俗的语言来讲清楚它俩之间到底存在着什么样的区别。同时还会告诉大家, 在不同的情况下应该选择使用哪种方式。另外, 文章后面还准备了可以拿来就直接使用的工具类代码, 这样即便是新手朋友们也能够非常快地上手操作了。一、核心区别在于: 利用一张表格来把对比的维度直观地显示出来, 从而看清对称加密和非对称加密这两者的不同。密钥特点加密和解密的过程用的是同一把密钥, 这把密钥是需要被严格保密的。是使用由公钥和私钥所组成的一对密钥来进行协同工作的其中, 公钥是可以公开给所有人的, 而私钥则必须是严格保密的。加密效率速度表现得非常快, 这一特性是非常适合处理那些数据体量相当大的加密任务的。它的速度是比较慢的, 原因是数学运算比较复杂, 这种方式更适合对小数据量进行加密操作。安全性系统的安全性其实全都依赖于保管好密钥, 一旦这个密钥发生了泄露的情况, 那么所有数据就会完全暴露出来。它的安全性变得更高了, 因为在整个过程中私钥不会被传输给其他任何人, 用户只需要自己把这个私钥保管好就行了。密钥分发密钥分发面临很大困难, 原因是需要依赖安全通道来进行传输工作, 不然的话很容易就受到拦截。密钥分发这个事情显得特别简单, 公钥这个玩意儿是可以公开传播的, 完全没有必要去保密。所谓的典型算法。AES、DES、3DESRSA、DSA、ECC二、各自用途的具体区别: 我们究竟该在什么时候使用哪一种加密方法呢? 关于第一点, 也就是所谓的对称加密, 它的应用场景非常适合针对大数据量进行的加密工作。对称加密的核心优势在于速度快, 因此它主要被用于对大量数据进行加密操作, 具体比如。拿一个实际的软件开发情境当作例子来说, 用户在一个手机端应用程序上面提交了需要进行实名身份核实的资料, 这里头包括了姓这一项, 还包括了身份证号码这一项。然后后端的服务器在接取到了这些信息之后, 非得要把这些数据进行加密处理, 接着才能存入到关系型数据库MySQL里面去存起来。在这个时候, 开发人员选择了AES这种对称密钥的加密方式来进行操作这么一通安排, 这样子做既能够有效地保障数据传输和存储的过程里面的安全度不受到损害, 同时啊也不会因为花费太多的时光来进行加密计算这个操作, 而对整个接口的响应运行速度产生任何负面的影响作用。2. 非对称加密这一方法, 是在“密钥交换”与“数字签名”这些具体的场景场合下面, 是比较适合被进行使用的。非对称加密这种技术手段, 它最主要的长处在于安全性非常可靠, 而且密钥的分发过程也比较容易去管理, 可是它的计算速度确实比较慢, 因此在实际的应用场景中通常主要是用来:我们来看一个在开发过程中实际会碰到的场景, 当这个APP和服务器端头一回建立起连接的时候, 彼此之间需要对齐一个用来做数据加密的密钥, 而且这种密钥属于对称加密类型, 这是为了给之后传来的各种数据传输提供加密保护的。在这个阶段, 后端方面会专门去生成一套RSA公钥以及配套的私钥, 接着把那个公钥发送出去, 交给APP那边来处理。一旦APP拿到了这个公钥, 就会利用它对自己刚刚生成的AES密钥进行加密操作, 然后把加密后的东西送回后端, 后端拿到之后, 就会拿出自己手里的私钥来执行解密动作, 从而顺利得到那个AES密钥。等到后面正式传输数据的阶段了, 大家就直接运用刚确定的AES密钥来进行加密处理, 这样子的做法一方面解决了对称密钥应该怎样安全地分发给对方这个问题, 另一方面也充分保证了整个传输过程的工作效率, 可谓是一举两得。三、这是一个关于Java工具类实战的内容, 里面的代码可以直接复制使用, 第一个部分讲解的是对称加密工具类, 这里具体使用的是AES算法。在现在这个时期, AES是那种大家用得最多的对称加密算法。这个东西安全性是很高的, 运行效率也是挺快的。所以, 我们一般都推荐去优先地使用它。在下面这里提到的工具类里头, 它是能够支持对还有这两种模式进行加密的, 不仅包含了可以执行加密的动作, 也包含了可以执行解密的动作, 同时, 还具备了能够生成密钥的这个功能方面的内容:import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import java.util.Base64;/*** AES对称加密工具类可直接复用* 说明128位密钥无需额外配置256位密钥需安装JCE无限制权限文件*/public class AesEncryptUtil {// 加密算法AES模式ECB填充方式PKCS5Padding实际开发推荐用CBC模式需加偏移量private static final String ALGORITHM AES/ECB/PKCS5Padding;private static final String KEY_ALGORITHM AES;private static final int KEY_SIZE 128; // 密钥长度128/256/*** 生成AES密钥返回Base64编码后的密钥字符串方便存储*/public static String generateKey() throws Exception {KeyGenerator keyGenerator KeyGenerator.getInstance(KEY_ALGORITHM);keyGenerator.init(KEY_SIZE);SecretKey secretKey keyGenerator.generateKey();return Base64.getEncoder().encodeToString(secretKey.getEncoded());}/*** 加密明文 - Base64编码的密文* param plainText 明文待加密的字符串* param keyStr Base64编码后的密钥*/public static String encrypt(String plainText, String keyStr) throws Exception {// 1. 解码密钥byte[] keyBytes Base64.getDecoder().decode(keyStr);SecretKeySpec secretKey new SecretKeySpec(keyBytes, KEY_ALGORITHM);// 2. 初始化加密器Cipher cipher Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, secretKey);// 3. 加密并返回Base64编码的密文byte[] encryptBytes cipher.doFinal(plainText.getBytes(UTF-8));return Base64.getEncoder().encodeToString(encryptBytes);}/*** 解密Base64编码的密文 - 明文* param cipherText Base64编码后的密文* param keyStr Base64编码后的密钥*/public static String decrypt(String cipherText, String keyStr) throws Exception {// 1. 解码密钥和密文byte[] keyBytes Base64.getDecoder().decode(keyStr);byte[] cipherBytes Base64.getDecoder().decode(cipherText);SecretKeySpec secretKey new SecretKeySpec(keyBytes, KEY_ALGORITHM);// 2. 初始化解密器Cipher cipher Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, secretKey);// 3. 解密并返回明文byte[] decryptBytes cipher.doFinal(cipherBytes);return new String(decryptBytes, UTF-8);}// 测试方法public static void main(String[] args) throws Exception {// 1. 生成密钥实际开发中密钥需妥善保管如配置在Nacos、Vault中String key generateKey();System.out.println(AES密钥Base64编码 key);// 2. 加密String plainText 用户身份证号110101199001011234;String cipherText encrypt(plainText, key);System.out.println(加密后的密文 cipherText);// 3. 解密String decryptText decrypt(cipherText, key);System.out.println(解密后的明文 decryptText);}}2. 非对称加密工具类RSA算法在现在这个时期里头, RSA是属于那些最常用的非对称加密算法中的一种, 它比较适合用来做密钥交换以及数字签名这样的事情, 下面所展示的这个工具类里面, 它是包含了密钥对生成、公钥加密、私钥解密、私钥签名、还有公钥验签这些个功能的。import javax.crypto.Cipher;import java.security.*;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;/*** RSA非对称加密工具类可直接复用* 说明密钥长度推荐2048位安全性足够4096位加密速度较慢*/public class RsaEncryptUtil {private static final String ALGORITHM RSA;private static final int KEY_SIZE 2048; // 密钥长度2048/4096// 签名算法SHA256withRSASHA256哈希RSA签名安全性更高private static final String SIGN_ALGORITHM SHA256withRSA;/*** 生成RSA密钥对公钥私钥返回Base64编码后的字符串* return 数组[0]公钥[1]私钥*/public static String[] generateKeyPair() throws Exception {KeyPairGenerator keyPairGenerator KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(KEY_SIZE);KeyPair keyPair keyPairGenerator.generateKeyPair();// 公钥编码为Base64字符串String publicKey Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());// 私钥编码为Base64字符串String privateKey Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());return new String[]{publicKey, privateKey};}/*** 公钥加密适合加密小数据如AES密钥* param plainText 明文待加密的字符串* param publicKeyStr Base64编码后的公钥*/public static String encryptByPublicKey(String plainText, String publicKeyStr) throws Exception {// 1. 解码公钥byte[] publicKeyBytes Base64.getDecoder().decode(publicKeyStr);X509EncodedKeySpec keySpec new X509EncodedKeySpec(publicKeyBytes);KeyFactory keyFactory KeyFactory.getInstance(ALGORITHM);PublicKey publicKey keyFactory.generatePublic(keySpec);// 2. 初始化加密器Cipher cipher Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 3. 加密RSA加密有长度限制需分段加密这里简化处理短字符串byte[] encryptBytes cipher.doFinal(plainText.getBytes(UTF-8));return Base64.getEncoder().encodeToString(encryptBytes);}/*** 私钥解密* param cipherText Base64编码后的密文* param privateKeyStr Base64编码后的私钥*/public static String decryptByPrivateKey(String cipherText, String privateKeyStr) throws Exception {// 1. 解码私钥byte[] privateKeyBytes Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec keySpec new PKCS8EncodedKeySpec(privateKeyBytes);KeyFactory keyFactory KeyFactory.getInstance(ALGORITHM);PrivateKey privateKey keyFactory.generatePrivate(keySpec);// 2. 初始化解密器Cipher cipher Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);// 3. 解密byte[] cipherBytes Base64.getDecoder().decode(cipherText);byte[] decryptBytes cipher.doFinal(cipherBytes);return new String(decryptBytes, UTF-8);}/*** 私钥签名用于数据防篡改、来源认证* param data 待签名的数据* param privateKeyStr Base64编码后的私钥*/public static String sign(String data, String privateKeyStr) throws Exception {// 1. 解码私钥byte[] privateKeyBytes Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec keySpec new PKCS8EncodedKeySpec(privateKeyBytes);KeyFactory keyFactory KeyFactory.getInstance(ALGORITHM);PrivateKey privateKey keyFactory.generatePrivate(keySpec);// 2. 生成签名Signature signature Signature.getInstance(SIGN_ALGORITHM);signature.initSign(privateKey);signature.update(data.getBytes(UTF-8));byte[] signBytes signature.sign();return Base64.getEncoder().encodeToString(signBytes);}/*** 公钥验签验证数据是否被篡改、签名是否有效* param data 原始数据* param sign 签名值Base64编码* param publicKeyStr Base64编码后的公钥*/public static boolean verifySign(String data, String sign, String publicKeyStr) throws Exception {// 1. 解码公钥byte[] publicKeyBytes Base64.getDecoder().decode(publicKeyStr);X509EncodedKeySpec keySpec new X509EncodedKeySpec(publicKeyBytes);KeyFactory keyFactory KeyFactory.getInstance(ALGORITHM);PublicKey publicKey keyFactory.generatePublic(keySpec);// 2. 验证签名Signature signature Signature.getInstance(SIGN_ALGORITHM);signature.initVerify(publicKey);signature.update(data.getBytes(UTF-8));return signature.verify(Base64.getDecoder().decode(sign));}// 测试方法public static void main(String[] args) throws Exception {// 1. 生成密钥对String[] keyPair generateKeyPair();String publicKey keyPair[0];String privateKey keyPair[1];System.out.println(RSA公钥Base64编码 publicKey);System.out.println(RSA私钥Base64编码 privateKey);// 2. 加密解密加密AES密钥示例String aesKey 1234567890abcdef; // 假设生成的AES密钥String encryptAesKey encryptByPublicKey(aesKey, publicKey);System.out.println(公钥加密后的AES密钥 encryptAesKey);String decryptAesKey decryptByPrivateKey(encryptAesKey, privateKey);System.out.println(私钥解密后的AES密钥 decryptAesKey);// 3. 签名验签String data 接口返回数据{\code\:200,\msg\:\success\};String sign sign(data, privateKey);System.out.println(私钥签名值 sign);boolean verifyResult verifySign(data, sign, publicKey);System.out.println(公钥验签结果 verifyResult); // true表示验签通过}}四、在开发的时候要特别注意密钥的保管问题, 对称加密所用的密钥以及非对称加密所用的私钥, 是绝对不能直接把它们写死在代码里面的, 比较建议的做法是把它们存放在配置中心当中, 比如说可以是 Nacos 或者是使用像 Vault 这样的密钥管理工具, 其次是关于算法的选择方面, 在进行对称加密的时候应该优先选择 AES 这种方式, 千万不要去用 DES, 因为 DES 的安全性是比较低的, 而在进行非对称加密的时候, 要优先选用 RSA-2048, 这样能够同时兼顾到安全性和效率, 然后再看看数据长度这回事, RSA 这种加密方式是有长度限制的,举个例子来说, 如果用的是 2048 位的密钥, 那么它最多只能用来加密 245 个字节的数据, 如果要处理比较大的数据量, 就需要对其进行分段操作, 或者是使用非对称加密加上对称加密这种组合的方案来解决, 最后在填充方式这一块的处理上, 对于对称加密是比较推荐采用特定方式的, 主要是为了保持良好的兼容性, 而对于非对称加密呢, 其实是不需要手动去专门指定填充方式的, 因为在 Java 语言当中的默认实现已经做过优化了。总结到这里, 这篇讲述Java对称加密和不对称加密的区别、用途以及工具类的文章, 就介绍到这个地方了, 更多关于Java对称加密和不称加密相关内容的信息, 请大家去脚本之家以往的文章里面搜索一下, 或者继续查看下面推荐的这些相关文章, 希望读文章的大家以后能够多多支持csdn这个平台哦。
网站建设高端定制企业官网