本文目录导读:

我将为您提供一个全面的Java密码学案例,涵盖常见的加密算法、哈希函数和数字签名。
项目结构和基础依赖
<!-- Maven依赖 -->
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
</dependencies>
对称加密示例(AES)
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
public class AESExample {
private static final int KEY_SIZE = 128; // 128/192/256
private static final int IV_SIZE = 12; // GCM推荐12字节
private static final int TAG_SIZE = 128; // GCM认证标签长度
/**
* 使用AES-GCM加密(推荐,提供认证)
*/
public static String encryptWithGCM(String plaintext, byte[] key) throws Exception {
// 生成随机IV
byte[] iv = new byte[IV_SIZE];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
// 初始化加密器
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmSpec = new GCMParameterSpec(TAG_SIZE, iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
// 执行加密
byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
// 组合IV和密文
byte[] result = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(result);
}
/**
* 使用AES-GCM解密
*/
public static String decryptWithGCM(String ciphertext, byte[] key) throws Exception {
// 解码Base64
byte[] data = Base64.getDecoder().decode(ciphertext);
// 提取IV和密文
byte[] iv = new byte[IV_SIZE];
byte[] encrypted = new byte[data.length - IV_SIZE];
System.arraycopy(data, 0, iv, 0, iv.length);
System.arraycopy(data, iv.length, encrypted, 0, encrypted.length);
// 初始化解密器
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmSpec = new GCMParameterSpec(TAG_SIZE, iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
// 执行解密
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, "UTF-8");
}
/**
* 生成AES密钥
*/
public static byte[] generateKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(KEY_SIZE);
SecretKey secretKey = keyGen.generateKey();
return secretKey.getEncoded();
}
public static void main(String[] args) {
try {
// 生成密钥
byte[] key = generateKey();
// 测试加密解密
String originalText = "Hello, Java Cryptography! 这是一个测试内容。";
String encrypted = encryptWithGCM(originalText, key);
System.out.println("原始文本: " + originalText);
System.out.println("加密结果: " + encrypted);
String decrypted = decryptWithGCM(encrypted, key);
System.out.println("解密结果: " + decrypted);
System.out.println("加解密成功: " + originalText.equals(decrypted));
} catch (Exception e) {
e.printStackTrace();
}
}
}
非对称加密示例(RSA)
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAExample {
private static final int KEY_SIZE = 2048;
/**
* 生成RSA密钥对
*/
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(KEY_SIZE);
return keyGen.generateKeyPair();
}
/**
* 使用公钥加密
*/
public static String encrypt(String plaintext, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* 使用私钥解密
*/
public static String decrypt(String ciphertext, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
return new String(decrypted, "UTF-8");
}
/**
* 使用私钥签名
*/
public static byte[] sign(String data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data.getBytes("UTF-8"));
return signature.sign();
}
/**
* 使用公钥验签
*/
public static boolean verify(String data, byte[] signatureBytes, PublicKey publicKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data.getBytes("UTF-8"));
return signature.verify(signatureBytes);
}
public static void main(String[] args) {
try {
// 生成密钥对
KeyPair keyPair = generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 测试加密解密
String originalText = "RSA非对称加密测试";
String encrypted = encrypt(originalText, publicKey);
System.out.println("RSA加密结果: " + encrypted);
String decrypted = decrypt(encrypted, privateKey);
System.out.println("RSA解密结果: " + decrypted);
// 测试数字签名
String data = "需要签名的数据";
byte[] signature = sign(data, privateKey);
boolean isVerified = verify(data, signature, publicKey);
System.out.println("签名验证结果: " + isVerified);
} catch (Exception e) {
e.printStackTrace();
}
}
}
哈希函数示例
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class HashExample {
/**
* 计算MD5哈希值
*/
public static String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
return toHexString(digest);
}
/**
* 计算SHA-256哈希值
*/
public static String sha256(String input) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(input.getBytes());
return toHexString(hash);
}
/**
* 计算SHA-512哈希值
*/
public static String sha512(String input) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
byte[] hash = digest.digest(input.getBytes());
return toHexString(hash);
}
/**
* 使用盐值的SHA-256哈希(推荐用于密码存储)
*/
public static String saltedHash(String password, String salt) throws NoSuchAlgorithmException {
String saltedPassword = salt + password;
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(saltedPassword.getBytes());
return toHexString(hash);
}
/**
* 字节数组转十六进制字符串
*/
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* 生成随机盐值
*/
public static String generateSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
public static void main(String[] args) {
try {
String text = "Hello, Hash Functions!";
System.out.println("MD5: " + md5(text));
System.out.println("SHA-256: " + sha256(text));
System.out.println("SHA-512: " + sha512(text));
// 密码哈希示例
String password = "myPassword123";
String salt = generateSalt();
String hashedPassword = saltedHash(password, salt);
System.out.println("\n密码哈希测试:");
System.out.println("盐值: " + salt);
System.out.println("哈希结果: " + hashedPassword);
// 验证
String inputPassword = "myPassword123";
String inputHash = saltedHash(inputPassword, salt);
System.out.println("密码验证: " + hashedPassword.equals(inputHash));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
完整的密码管理器工具类
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Properties;
/**
* 综合密码学工具类
*/
public class CryptoUtils {
// 加密算法常量
public static final String AES = "AES";
public static final String RSA = "RSA";
public static final String HMAC_SHA256 = "HmacSHA256";
/**
* 文件加解密(AES)
*/
public static void encryptFile(File inputFile, File outputFile, byte[] key) throws Exception {
// 生成随机IV
byte[] iv = new byte[16];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, AES);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new java.security.spec.IvParameterSpec(iv));
try (FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile)) {
// 写入IV
fos.write(iv);
// 加密并写入
byte[] buffer = new byte[8192];
byte[] encrypted;
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
encrypted = cipher.update(buffer, 0, bytesRead);
if (encrypted != null) {
fos.write(encrypted);
}
}
encrypted = cipher.doFinal();
if (encrypted != null) {
fos.write(encrypted);
}
}
}
/**
* 文件解密(AES)
*/
public static void decryptFile(File inputFile, File outputFile, byte[] key) throws Exception {
try (FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile)) {
// 读取IV
byte[] iv = new byte[16];
fis.read(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, AES);
cipher.init(Cipher.DECRYPT_MODE, keySpec, new java.security.spec.IvParameterSpec(iv));
// 解密并写入
byte[] buffer = new byte[8192];
byte[] decrypted;
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
decrypted = cipher.update(buffer, 0, bytesRead);
if (decrypted != null) {
fos.write(decrypted);
}
}
decrypted = cipher.doFinal();
if (decrypted != null) {
fos.write(decrypted);
}
}
}
/**
* HMAC-SHA256消息认证码
*/
public static String hmacSha256(String message, String secret) throws Exception {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance(HMAC_SHA256);
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes("UTF-8"), HMAC_SHA256);
mac.init(keySpec);
byte[] hmac = mac.doFinal(message.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(hmac);
}
/**
* 密钥文件的保存和加载
*/
public static void saveKey(SecretKey key, String filePath, char[] password) throws Exception {
// 使用密码保护密钥
byte[] encodedKey = key.getEncoded();
// 简单加密(实际应用中应使用更安全的方式)
byte[] protectedKey = xorWithPassword(encodedKey, password);
try (FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(protectedKey);
}
}
public static SecretKey loadKey(String filePath, char[] password) throws Exception {
byte[] protectedKey = Files.readAllBytes(Paths.get(filePath));
byte[] encodedKey = xorWithPassword(protectedKey, password);
return new SecretKeySpec(encodedKey, AES);
}
// 简单的XOR加密(仅用于示例,实际应用使用推荐使用KeyStore)
private static byte[] xorWithPassword(byte[] data, char[] password) {
byte[] keyBytes = new String(password).getBytes();
byte[] result = new byte[data.length];
for (int i = 0; i < data.length; i++) {
result[i] = (byte) (data[i] ^ keyBytes[i % keyBytes.length]);
}
return result;
}
/**
* 安全字符串比较(防止时序攻击)
*/
public static boolean secureCompare(String str1, String str2) {
return MessageDigest.isEqual(
str1.getBytes(),
str2.getBytes()
);
}
/**
* 生成安全的强随机数
*/
public static byte[] generateSecureRandomBytes(int length) {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[length];
secureRandom.nextBytes(bytes);
return bytes;
}
public static void main(String[] args) {
try {
// 测试文件加密
String testContent = "This is a secret file content!";
File tempFile = File.createTempFile("test", ".txt");
File encryptedFile = File.createTempFile("encrypted", ".bin");
File decryptedFile = File.createTempFile("decrypted", ".txt");
// 写入测试内容
Files.write(tempFile.toPath(), testContent.getBytes());
// 生成密钥
byte[] key = generateSecureRandomBytes(16); // 128位密钥
// 加密文件
encryptFile(tempFile, encryptedFile, key);
System.out.println("文件已加密: " + encryptedFile.length() + " bytes");
// 解密文件
decryptFile(encryptedFile, decryptedFile, key);
String decryptedContent = new String(Files.readAllBytes(decryptedFile.toPath()));
System.out.println("解密内容: " + decryptedContent);
System.out.println("文件加解密成功: " + testContent.equals(decryptedContent));
// 测试HMAC
String message = "Important message";
String hmac = hmacSha256(message, "secret-key");
System.out.println("\nHMAC-SHA256: " + hmac);
// 清理临时文件
tempFile.delete();
encryptedFile.delete();
decryptedFile.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键点说明
对称加密特点:
- AES-GCM:提供认证加密,防止篡改
- 密钥管理:需要安全地存储和交换密钥
- 性能:适合大数据量加密
非对称加密特点:
- RSA:适合小数据量和密钥交换
- 数字签名:确保数据完整性和来源认证
- 公钥/私钥:公钥用于加密,私钥用于解密
安全实践建议:
- 使用 AES-256-GCM 进行数据加密
- 使用 RSA-2048或更高 进行签名和密钥交换
- 密码存储使用 加盐的SHA-256或bcrypt
- 使用 SecureRandom 生成随机数
- 避免使用 MD5和SHA-1(已不安全)
- 使用 TLS/SSL 保护传输数据
这个案例提供了Java密码学的核心实现,可用于实际项目中的安全需求,需要根据具体场景选择合适的加密方案。