Java 常用文本加解密工具类总结

305 阅读8分钟

经典加密算法总结:

算法名称类别描述是否安全
DES对称加密算法数据加密标准,56位密钥长度,被认为不再安全不安全
3DES对称加密算法三重数据加密算法,通过对DES的改进提高了安全性较安全
AES对称加密算法高级加密标准,支持128、196、256位密钥长度,目前最流行的对称加密算法之一安全
RSA非对称加密算法最著名的非对称加密算法之一,广泛应用于数据传输的加密和数字签名安全
DSA非对称加密算法数字签名算法,主要用于生成和验证数字签名安全
ECC非对称加密算法椭圆曲线密码学,适合在资源受限的环境中使用,提供高效的加密和解密安全
MD5散列函数虽然曾经广泛使用,但现在由于存在碰撞攻击的风险,已经不再建议用于安全的场合不安全
SHA-1散列函数安全散列算法,已被发现存在安全漏洞,不推荐用于新应用不安全
SHA-256散列函数安全散列算法,提供较高的安全性,广泛用于数据完整性验证安全
SHA-348/512散列函数安全散列算法,提供更高的安全性,适用于需要更强安全性的场景安全
Base64其他加密方法编码方法,用于将二进制数据转换为文本格式以便在网络上传输不是加密,仅编码
Blowflsh其他加密方法对称加密算法,支持可变长度的密钥,由 Bruce Schneier 设计安全
RC4其他加密方法流加密算法,曾经非常流行,但现在由于存在安全弱点,不推荐用于新的应用不安全

国密算法:

算法名称类别描述应用实例
SM1对称加密算法SM1(SCB2)算法是一种分组密码算法,主要用于加密和解密数据,该算法未公开,仅以IP核的形式存在于芯片中应用于智能IC卡、智能密码钥匙、加密卡等安全产品
SM2非对称加密算法SM2算法,全称椭圆曲线公钥密码算法,是一种非对称密码算法,它的公钥加密算法和数字签名算法可满足多种密码应用中的通信加解密、身份认证和数据完整性、真实性的安全需求,可用于替代RSA国际算法支持SM2算法的国密SSL证书,实现HTTPS加密和身份可信认证
SM3杂凑算法(哈希算法)SM3算法,全称SM3密码杂凑算法,其安全性与SHA-256相当,该算法利用了简单运算的充分多次迭代,主要应用于数字签名、消息验证以及随机数的生成应用于国密SSL证书、车联网安全通信、智能电表
SM4对称加密算法SM4算法是一种分组密码算法,可用于替代DES/AES等国际密码算法,拥有和AES算法相同的密钥长度和分组长度,均为128比特。SM4算法可实现数据的加解密,以保证数据和信息的机密性应用于无线局域网芯片、金融领域的智能密码钥匙
SM7对称加密算法SM7算法是一种分组加密算法,分组长度为128比特,密钥长度为128比特,该算法未公开应用于门禁卡、工作证、一卡通等身份识别类产品
SM9非对称加密算法SM9算法,全称SM9标识加密算法,是基于标识的非对称加密算法,用椭圆曲线对实现的基于标识的数字签名算法、密钥交换协议、密钥封装机制和公钥加密与解密算法应用于电子邮件安全、智能终端保护、物联网安全
ZUC对称加密算法ZUC算法,全称祖冲之序列密码算法,是我国商用密码算法体系的重要组成部分,主要用于数据的机密性和完整性保护,是实现网络空间安全的基础算法和核心技术应用于数字图像加密、移动通信加密

1. AES 对称加解密

package com.example.demo.util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * AES对称加密
 *
 * @author wangbo
 * @date 2024/11/14
 */
public class AesUtil {

    private AesUtil() {
    }

    /**
     * 生成AES密钥
     *
     * @param password 加密密码
     * @return 密钥
     * @throws NoSuchAlgorithmException 密钥生成算法不支持异常
     */
    private static SecretKey generateAesKey(String password) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        byte[] passwordBytes = password.getBytes(StandardCharsets.UTF_8);
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] keyBytes = digest.digest(passwordBytes);
        return new SecretKeySpec(keyBytes, "AES");
    }

    /**
     * 对称加密算法AES加密
     *
     * @param plaintext 待加密文本
     * @param password  加密密码
     * @return 加密后的密文
     * @throws Exception 加密异常
     */
    public static String encryptWithAes(String plaintext, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKey secretKey = generateAesKey(password);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 对称加密算法AES解密
     *
     * @param ciphertext 加密后的密文
     * @param password   加密密码
     * @return 解密后的明文
     * @throws Exception 解密异常
     */
    public static String decryptWithAes(String ciphertext, String password) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKey secretKey = generateAesKey(password);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) throws Exception {
        // AES 对称加密示例
        String plaintext = "Hello, world!";
        String password = "secretPassword";
        // AES 加密
        String encryptWithAes = encryptWithAes(plaintext, password);
        System.out.println("AES Encrypted: " + encryptWithAes);
        // AES 解密
        String decryptWithAes = decryptWithAes(encryptWithAes, password);
        System.out.println("AES Decrypted: " + decryptWithAes);
    }
}

2. RSA 非对称加解密

package com.example.demo.util;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RSA非对称加密
 *
 * @author wangbo
 * @date 2024/11/14
 */
public class RsaUtil {

    private RsaUtil() {
    }

    /**
     * 生成RSA密钥对
     *
     * @return 密钥对
     * @throws NoSuchAlgorithmException 密钥生成算法不支持异常
     */
    public static KeyPair generateRsaKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 获取RSA公钥的Base64编码字符串
     *
     * @return RSA公钥Base64编码字符串
     */
    public static String getRsaPublicKeyString(PublicKey publicKey) {
        KeyFactory keyFactory;
        try {
            keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
            return Base64.getEncoder().encodeToString(keyFactory.generatePublic(publicKeySpec).getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据Base64编码的字符串还原为RSA公钥
     *
     * @param publicKeyString RSA公钥Base64编码字符串
     * @return RSA公钥
     */
    public static PublicKey getPublicKey(String publicKeyString) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));
            return keyFactory.generatePublic(publicKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取RSA私钥的Base64编码字符串
     *
     * @return RSA私钥Base64编码字符串
     */
    public static String getRsaPrivateKeyString(PrivateKey privateKey) {
        KeyFactory keyFactory;
        try {
            keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
            return Base64.getEncoder().encodeToString(keyFactory.generatePrivate(privateKeySpec).getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据Base64编码的字符串还原为RSA私钥
     *
     * @param privateKeyString RSA私钥Base64编码字符串
     * @return RSA私钥
     */
    public static PrivateKey getPrivateKey(String privateKeyString) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));
            return keyFactory.generatePrivate(privateKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 非对称加密算法RSA加密
     *
     * @param plaintext 明文
     * @param publicKey 公钥
     * @return 加密后的密文
     * @throws Exception 加密异常
     */
    public static String encryptWithRsa(String plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 非对称加密算法RSA解密
     *
     * @param ciphertext 密文
     * @param privateKey 私钥
     * @return 解密后的明文
     * @throws Exception 解密异常
     */
    public static String decryptWithRsa(String ciphertext, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) throws Exception {
        //RSA非对称加密示例
        String plaintext = "Hello, RSA!";
        //生成RSA密钥对
        KeyPair keyPair = generateRsaKeyPair();
        //公钥字符串获取
        String publicKeyString = getRsaPublicKeyString(keyPair.getPublic());
        System.out.println("RSA publicKeyString: " + publicKeyString);
        //公钥还原
        PublicKey publicKey = getPublicKey(publicKeyString);
        //私钥字符串获取
        String privateKeyString = getRsaPrivateKeyString(keyPair.getPrivate());
        System.out.println("RSA privateKeyString: " + privateKeyString);
        //私钥还原
        PrivateKey privateKey = getPrivateKey(privateKeyString);
        // RSA公钥加密
        String encryptedRSA = encryptWithRsa(plaintext, publicKey);
        System.out.println("RSA Encrypted: " + encryptedRSA);
        // RSA私钥解密
        String decryptedRSA = decryptWithRsa(encryptedRSA, privateKey);
        System.out.println("RSA Decrypted: " + decryptedRSA);
    }
}

3. 哈希算法加密

package com.example.demo.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.DigestUtils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 哈希算法加密
 *
 * @author wangbo
 * @date 2024/11/14
 */
@Slf4j
public class HashUtil {

    private HashUtil() {
    }

    /**
     * 哈希算法SHA-256
     *
     * @param plaintext 明文
     * @return 哈希值
     * @throws NoSuchAlgorithmException 哈希算法不支持异常
     */
    public static String hashWithSha256(String plaintext) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(plaintext.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(hashBytes);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * SHA密码加密
     *
     * @param sourceStr 源字符串
     * @return 加密字符串
     */
    public static String sha(String sourceStr) {
        try {
            MessageDigest sha = MessageDigest.getInstance("SHA");
            sha.update(sourceStr.getBytes(StandardCharsets.UTF_8));
            return new BigInteger(1, sha.digest()).toString(32);
        } catch (NoSuchAlgorithmException e) {
            log.error("SHA字符串加密异常", e);
            return null;
        }
    }

    /**
     * MD5密码加密
     *
     * @param sourceStr 源字符串
     * @return 加密字符串
     */
    public static String md5(String sourceStr) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(sourceStr.getBytes(StandardCharsets.UTF_8));
            return new BigInteger(1, md5.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            log.error("MD5字符串加密异常", e);
            return null;
        }
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {
        String plaintext = "Hello Hash!";
        String hashValue = hashWithSha256(plaintext);
        System.out.println("SHA-256 Hash: " + hashValue);
        String sha = sha(plaintext);
        System.out.println("SHA: " + sha);
        String md5 = md5(plaintext);
        System.out.println("MD5: " + md5);
        //spring的工具类进行MD5加密
        String md5Spring = DigestUtils.md5DigestAsHex(plaintext.getBytes(StandardCharsets.UTF_8));
        System.out.println("MD5Spring: " + md5Spring);
        //commons-codec的工具类进行MD5加密
        String md5Commons = org.apache.commons.codec.digest.DigestUtils.md5Hex(plaintext);
        System.out.println("MD5Commons: " + md5Commons);
    }
}

如果使用 commons-codec 的工具类进行 MD5 加密,可能需要引入下面的依赖:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>${commons.codec.version}</version>
</dependency>

4. Base64 编解码

package com.example.demo.util;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * Base64
 *
 * @author wangbo
 * @date 2024/11/14
 */
public class Base64Util {

    private Base64Util() {
    }

    /**
     * Base64 编码
     *
     * @param plainText 内容
     * @return 十六进制字符串
     */
    public static String encodeBase64(String plainText) {
        byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
        return Base64.getEncoder().encodeToString(plainBytes);
    }

    /**
     * Base64 解码
     *
     * @param base64Text 十六进制字符串
     * @return 内容
     */
    public static String decodeBase64(String base64Text) {
        byte[] base64Bytes = Base64.getDecoder().decode(base64Text);
        return new String(base64Bytes, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {
        // Base64 编码
        String base64Text = Base64Util.encodeBase64("Hello Base64!");
        System.out.println("Base64 Encoded: " + base64Text);
        // Base64 解码
        String decodedText = Base64Util.decodeBase64(base64Text);
        System.out.println("Base64 Decoded: " + decodedText);
    }
}