本文目录导读:

我将为您提供一个全面的Java加密保护案例,涵盖多种常见的加密技术和最佳实践。
完整的加密工具类示例
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class EncryptionUtils {
// 对称加密(AES)
public static class AESUtil {
private static final String AES_ALGORITHM = "AES";
private static final String AES_TRANSFORMATION = "AES/GCM/NoPadding";
private static final int IV_SIZE = 12; // GCM推荐12字节
private static final int TAG_SIZE = 128; // GCM标签大小(位)
/**
* AES加密(GCM模式)
*/
public static String encrypt(String plainText, String key) throws Exception {
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
MessageDigest sha = MessageDigest.getInstance("SHA-256");
keyBytes = sha.digest(keyBytes);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, AES_ALGORITHM);
// 生成随机IV
byte[] iv = new byte[IV_SIZE];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_SIZE, iv));
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
// 组合IV和密文
byte[] result = new byte[IV_SIZE + encryptedBytes.length];
System.arraycopy(iv, 0, result, 0, IV_SIZE);
System.arraycopy(encryptedBytes, 0, result, IV_SIZE, encryptedBytes.length);
return Base64.getEncoder().encodeToString(result);
}
/**
* AES解密(GCM模式)
*/
public static String decrypt(String encryptedText, String key) throws Exception {
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
// 提取IV和密文
byte[] iv = new byte[IV_SIZE];
byte[] cipherBytes = new byte[encryptedBytes.length - IV_SIZE];
System.arraycopy(encryptedBytes, 0, iv, 0, IV_SIZE);
System.arraycopy(encryptedBytes, IV_SIZE, cipherBytes, 0, cipherBytes.length);
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
MessageDigest sha = MessageDigest.getInstance("SHA-256");
keyBytes = sha.digest(keyBytes);
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(TAG_SIZE, iv));
byte[] decryptedBytes = cipher.doFinal(cipherBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
}
// 非对称加密(RSA)
public static class RSAUtil {
private PrivateKey privateKey;
private PublicKey publicKey;
/**
* 生成密钥对
*/
public void generateKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
this.privateKey = keyPair.getPrivate();
this.publicKey = keyPair.getPublic();
}
/**
* RSA加密(使用公钥)
*/
public String encrypt(String plainText) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
/**
* RSA解密(使用私钥)
*/
public String decrypt(String encryptedText) throws Exception {
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
/**
* 获取公钥字符串
*/
public String getPublicKeyString() {
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
/**
* 获取私钥字符串(应安全存储)
*/
public String getPrivateKeyString() {
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
/**
* 从字符串加载公钥
*/
public void loadPublicKey(String publicKeyString) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(publicKeyString);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.publicKey = keyFactory.generatePublic(spec);
}
/**
* 从字符串加载私钥
*/
public void loadPrivateKey(String privateKeyString) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
this.privateKey = keyFactory.generatePrivate(spec);
}
}
// 哈希函数
public static class HashUtil {
/**
* SHA-256哈希
*/
public static String sha256(String input) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}
/**
* SHA-512哈希(更安全)
*/
public static String sha512(String input) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}
/**
* PBKDF2密码哈希(用于密码存储)
*/
public static String pbkdf2Hash(String password, String salt, int iterations, int keyLength)
throws Exception {
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(),
salt.getBytes(StandardCharsets.UTF_8),
iterations, keyLength);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();
return bytesToHex(hash);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
// 数字签名
public static class DigitalSignatureUtil {
private PrivateKey privateKey;
private PublicKey publicKey;
/**
* 生成签名
*/
public String sign(String data) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = signature.sign();
return Base64.getEncoder().encodeToString(signatureBytes);
}
/**
* 验证签名
*/
public boolean verify(String data, String signatureString) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = Base64.getDecoder().decode(signatureString);
return signature.verify(signatureBytes);
}
}
}
应用示例 - 用户认证系统
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class UserAuthenticationService {
private static final ConcurrentHashMap<String, UserAccount> users = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, TokenInfo> activeTokens = new ConcurrentHashMap<>();
// 用户账户类
public static class UserAccount {
private String username;
private String passwordHash;
private String salt;
private String email;
private Date createdAt;
public UserAccount(String username, String passwordHash, String salt, String email) {
this.username = username;
this.passwordHash = passwordHash;
this.salt = salt;
this.email = email;
this.createdAt = new Date();
}
// Getters and setters...
}
// 令牌信息类
public static class TokenInfo {
private String token;
private String username;
private Date expiryDate;
public TokenInfo(String token, String username, Date expiryDate) {
this.token = token;
this.username = username;
this.expiryDate = expiryDate;
}
public boolean isExpired() {
return expiryDate.before(new Date());
}
// Getters and setters...
}
/**
* 用户注册
*/
public boolean register(String username, String password, String email) {
if (users.containsKey(username)) {
return false;
}
try {
// 生成随机盐值
String salt = generateSalt();
// 使用PBKDF2进行密码哈希
String passwordHash = EncryptionUtils.HashUtil.pbkdf2Hash(password, salt, 10000, 256);
// 创建用户账户
UserAccount account = new UserAccount(username, passwordHash, salt, email);
users.put(username, account);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 用户登录
*/
public String login(String username, String password) {
UserAccount account = users.get(username);
if (account == null) {
return null;
}
try {
// 验证密码
String hash = EncryptionUtils.HashUtil.pbkdf2Hash(password, account.salt, 10000, 256);
if (!hash.equals(account.passwordHash)) {
return null;
}
// 生成访问令牌
String token = generateToken();
Date expiryDate = new Date(System.currentTimeMillis() + 30 * 60 * 1000); // 30分钟
TokenInfo tokenInfo = new TokenInfo(token, username, expiryDate);
activeTokens.put(token, tokenInfo);
return token;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 验证令牌
*/
public boolean verifyToken(String token) {
TokenInfo tokenInfo = activeTokens.get(token);
if (tokenInfo == null || tokenInfo.isExpired()) {
activeTokens.remove(token); // 清理过期令牌
return false;
}
return true;
}
/**
* 密码重置(演示加密数据的应用)
*/
public boolean resetPassword(String username, String oldPassword, String newPassword) {
UserAccount account = users.get(username);
if (account == null) {
return false;
}
try {
// 验证旧密码
String oldHash = EncryptionUtils.HashUtil.pbkdf2Hash(oldPassword, account.salt, 10000, 256);
if (!oldHash.equals(account.passwordHash)) {
return false;
}
// 更新密码
String newSalt = generateSalt();
String newHash = EncryptionUtils.HashUtil.pbkdf2Hash(newPassword, newSalt, 10000, 256);
// 更新用户账户(实际应用中需要更新数据库)
// account.setPasswordHash(newHash);
// account.setSalt(newSalt);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// 辅助方法
private String generateSalt() {
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
private String generateToken() {
return UUID.randomUUID().toString() + System.currentTimeMillis();
}
}
文件加密示例
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.SecureRandom;
public class FileEncryptionUtil {
/**
* 加密文件
*/
public static void encryptFile(String sourceFilePath, String destFilePath, String key)
throws Exception {
// 生成随机IV
byte[] ivBytes = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(ivBytes);
// 初始化密钥
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(ivBytes));
try (FileInputStream inputStream = new FileInputStream(sourceFilePath);
FileOutputStream outputStream = new FileOutputStream(destFilePath)) {
// 写入IV到文件头部
outputStream.write(ivBytes);
// 加密内容
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
}
}
/**
* 解密文件
*/
public static void decryptFile(String sourceFilePath, String destFilePath, String key)
throws Exception {
try (FileInputStream inputStream = new FileInputStream(sourceFilePath);
FileOutputStream outputStream = new FileOutputStream(destFilePath)) {
// 读取IV
byte[] ivBytes = new byte[16];
int ivRead = inputStream.read(ivBytes);
if (ivRead != 16) {
throw new IllegalArgumentException("加密文件格式错误");
}
// 初始化密钥
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(ivBytes));
// 解密内容
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
}
}
/**
* 安全的文件删除(覆盖后再删除)
*/
public static void secureDeleteFile(String filePath) throws IOException {
Path path = Paths.get(filePath);
if (!Files.exists(path)) {
return;
}
// 获取文件大小
long size = Files.size(path);
// 多次覆盖文件内容
try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
raf.seek(0);
raf.write(new byte[(int) size]);
raf.getFD().sync();
}
// 删除文件
Files.deleteIfExists(path);
}
}
安全最佳实践和注意事项
public class SecurityBestPractices {
/**
* 1. 使用安全的随机数生成器
*/
public static byte[] generateSecureRandomBytes(int length) {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[length];
secureRandom.nextBytes(bytes);
return bytes;
}
/**
* 2. 正确的密码存储方式
*/
public static String hashPasswordCorrectly(String password) {
try {
// 使用BCrypt(通过第三方库)或Argon2(推荐)
// 这里使用PBKDF2作为示例
String salt = generateSalt();
int iterations = 10000; // 应该足够大
int keyLength = 256;
return EncryptionUtils.HashUtil.pbkdf2Hash(password, salt, iterations, keyLength);
} catch (Exception e) {
throw new RuntimeException("密码哈希失败", e);
}
}
/**
* 3. 使用密钥管理系统(示例接口)
*/
public interface KeyManagementService {
String generateKey();
String generateIV();
String encryptKeyWithMasterKey(String key);
String decryptKeyWithMasterKey(String encryptedKey);
void rotateKey(String keyId);
}
/**
* 4. 内容加密vs哈希的区别
*/
public static class HashingVsEncryption {
// 哈希:不可逆,用于密码验证
public static String hashForVerification(String data) throws Exception {
return EncryptionUtils.HashUtil.sha256(data);
}
// 加密:可逆,用于数据传输和存储
public static String encryptForStorage(String data, String key) throws Exception {
return EncryptionUtils.AESUtil.encrypt(data, key);
}
}
/**
* 5. 安全的字符串比较(防止时序攻击)
*/
public static boolean secureCompare(String str1, String str2) {
if (str1 == null || str2 == null) return false;
byte[] bytes1 = str1.getBytes(StandardCharsets.UTF_8);
byte[] bytes2 = str2.getBytes(StandardCharsets.UTF_8);
if (bytes1.length != bytes2.length) return false;
int result = 0;
for (int i = 0; i < bytes1.length; i++) {
result |= bytes1[i] ^ bytes2[i];
}
return result == 0;
}
private static String generateSalt() {
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
}
使用示例
public class EncryptionExample {
public static void main(String[] args) {
try {
// 1. AES加密示例
String plainText = "Hello, 这是一个加密示例!";
String aesKey = "MySecretKey123";
String encrypted = EncryptionUtils.AESUtil.encrypt(plainText, aesKey);
String decrypted = EncryptionUtils.AESUtil.decrypt(encrypted, aesKey);
System.out.println("AES加密结果: " + encrypted);
System.out.println("AES解密结果: " + decrypted);
// 2. RSA加密示例
EncryptionUtils.RSAUtil rsaUtil = new EncryptionUtils.RSAUtil();
rsaUtil.generateKeyPair();
String rsaEncrypted = rsaUtil.encrypt(plainText);
String rsaDecrypted = rsaUtil.decrypt(rsaEncrypted);
System.out.println("RSA加密结果: " + rsaEncrypted);
System.out.println("RSA解密结果: " + rsaDecrypted);
// 3. 哈希示例
String hash = EncryptionUtils.HashUtil.sha256(plainText);
System.out.println("SHA-256哈希: " + hash);
// 4. 密码存储示例
UserAuthenticationService authService = new UserAuthenticationService();
authService.register("user1", "Password123!", "user1@example.com");
String token = authService.login("user1", "Password123!");
System.out.println("用户认证令牌: " + token);
System.out.println("令牌验证结果: " + authService.verifyToken(token));
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键安全建议
-
密钥管理
- 永远不要硬编码密钥在代码中
- 使用专业的密钥管理服务(如AWS KMS、HashiCorp Vault)
-
算法选择
- 数据加密:AES-256-GCM
- 密钥交换:RSA-2048 或 ECC
- 密码存储:Argon2、BCrypt、scrypt(PBKDF2作为备选)
-
安全实践
- 使用随机IV
- 实施密钥轮换策略
- 记录安全事件日志
- 定期进行安全审计
-
传输安全
- 始终使用HTTPS/TLS
- 实施证书固定
- 使用HSTS
这个案例涵盖了Java加密的主要方面,实际项目中应根据具体需求选择合适的加密方案。