上一篇
Java如何简单加密解密数据?示例?
- 后端开发
- 2025-06-07
- 3556
在Java中实现加密解密可使用javax.crypto包工具类,常用步骤:1. 通过KeyGenerator生成密钥;2. 创建Cipher实例配置加密模式(如AES/DES);3. 调用doFinal()执行加解密操作,关键类包含Cipher、SecretKey和KeyGenerator,注意遵循安全规范处理密钥和初始化向量。
在Java中实现加密与解密是保障数据安全的核心技能,通过标准库javax.crypto
和java.security
可高效完成,以下详细实现方案遵循最佳实践,兼顾安全性与实用性:
加密基础概念
-
对称加密
加密解密使用同一密钥,速度快,适合大数据量(如AES、DES)。// 密钥生成示例(AES-256) KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); // 密钥长度 SecretKey secretKey = keyGen.generateKey();
-
非对称加密
使用公钥加密、私钥解密,安全性高但速度慢(如RSA)。// 密钥对生成 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); // 密钥长度 KeyPair keyPair = keyPairGen.generateKeyPair();
-
关键参数
- 算法模式:如
AES/CBC/PKCS5Padding
(CBC需初始化向量IV) - 密钥管理:使用
KeyStore
或硬件安全模块(HSM)存储密钥 - 填充方案:PKCS#5/PKCS#7防止数据块长度不足
- 算法模式:如
对称加密实战(AES)
import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import java.util.Base64; import java.security.SecureRandom; public class AESEncryption { // 加密 public static String encrypt(String plaintext, SecretKey key) throws Exception { byte[] iv = new byte[16]; // 初始化向量(IV) SecureRandom random = new SecureRandom(); random.nextBytes(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); byte[] ciphertext = cipher.doFinal(plaintext.getBytes()); // 合并IV和密文(IV无需保密) byte[] combined = new byte[iv.length + ciphertext.length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length); return Base64.getEncoder().encodeToString(combined); } // 解密 public static String decrypt(String encrypted, SecretKey key) throws Exception { byte[] combined = Base64.getDecoder().decode(encrypted); byte[] iv = new byte[16]; byte[] ciphertext = new byte[combined.length - 16]; System.arraycopy(combined, 0, iv, 0, 16); System.arraycopy(combined, 16, ciphertext, 0, ciphertext.length); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); return new String(cipher.doFinal(ciphertext)); } }
非对称加密实战(RSA)
import javax.crypto.Cipher; import java.security.*; import java.util.Base64; public class RSAEncryption { // 公钥加密 public static String encrypt(String plaintext, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] ciphertext = cipher.doFinal(plaintext.getBytes()); return Base64.getEncoder().encodeToString(ciphertext); } // 私钥解密 public static String decrypt(String encrypted, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] plaintext = cipher.doFinal(Base64.getDecoder().decode(encrypted)); return new String(plaintext); } }
关键安全实践
-
初始化向量(IV)
- 必须使用密码学安全随机数生成(
SecureRandom
) - 每次加密更换IV,禁止硬编码
- 必须使用密码学安全随机数生成(
-
密钥管理规范
// 推荐密钥存储方式 KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(null, null); keyStore.setEntry("alias", new KeyStore.SecretKeyEntry(secretKey), new KeyStore.PasswordProtection("password".toCharArray()));
-
算法选择优先级
AES-256 GCM > AES-256 CBC > RSA-3072(非对称)
-
防御常见攻击
- 使用
OAEP
填充代替PKCS1Padding
(抵御填充预言攻击) - 验证解密后数据完整性(如HMAC)
- 使用
典型错误与修正
错误示例 | 风险 | 修正方案 |
---|---|---|
硬编码密钥 | 密钥泄漏 | 从安全存储(如HashiCorp Vault)动态获取 |
固定IV | 相同明文生成相同密文 | 每次加密随机生成IV |
使用ECB模式 | 数据模式泄漏 | 改用CBC或GCM模式 |
忽略异常处理 | 敏感信息泄露 | 捕获GeneralSecurityException 并转换为自定义错误 |
性能优化建议
- 对称加密大数据:分段处理(
Cipher.update()
+Cipher.doFinal()
) - 非对称场景:仅加密对称密钥(RSA封装AES密钥)
- 线程安全:每个线程创建独立
Cipher
实例(避免复用)
// 分段加密示例(适合大文件) cipher.init(Cipher.ENCRYPT_MODE, key); try (FileInputStream in = new FileInputStream("input.txt"); FileOutputStream out = new FileOutputStream("encrypted.bin")) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { byte[] encryptedBlock = cipher.update(buffer, 0, bytesRead); if (encryptedBlock != null) out.write(encryptedBlock); } out.write(cipher.doFinal()); // 处理最后一块 }
引用说明
本文代码遵循Java Cryptography Architecture (JCA)标准,参考:
- Oracle官方安全指南
- NIST特别出版物800-38A(加密模式规范)
密钥管理建议依据OWASP密钥管理规范。
实际部署请结合硬件安全模块(HSM)或密钥管理服务(KMS)。