Java密码学案例

wen java案例 2

本文目录导读:

Java密码学案例

  1. 项目结构和基础依赖
  2. 对称加密示例(AES)
  3. 非对称加密示例(RSA)
  4. 哈希函数示例
  5. 完整的密码管理器工具类
  6. 关键点说明

我将为您提供一个全面的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:适合小数据量和密钥交换
  • 数字签名:确保数据完整性和来源认证
  • 公钥/私钥:公钥用于加密,私钥用于解密

安全实践建议:

  1. 使用 AES-256-GCM 进行数据加密
  2. 使用 RSA-2048或更高 进行签名和密钥交换
  3. 密码存储使用 加盐的SHA-256或bcrypt
  4. 使用 SecureRandom 生成随机数
  5. 避免使用 MD5和SHA-1(已不安全)
  6. 使用 TLS/SSL 保护传输数据

这个案例提供了Java密码学的核心实现,可用于实际项目中的安全需求,需要根据具体场景选择合适的加密方案。

抱歉,评论功能暂时关闭!