Java实现常用加密算法汇总(建议收藏)

系列文章目录

第一章:Java实现常用加密算法 —— MD5
第二章:Java实现常用加密算法 —— SHA256



前言

本篇主要介绍了各种常用的加密算法在Java(JDK1.8)中如何实现,借助Java标准库或第三方库,非原始实现,较为基础。各个算法的具体介绍或实现方法请参见系列其他文章,本文为汇总,可以照抄作业。


一、各算法对比

根据是否可逆是否对称对算法进行分类,是否可逆其实就是是否能进行解密操作

是否可逆算法
不可逆MD5、SHA-256、SM3、HMAC
可逆对称:DES、AES、SM1、SM4,不对称:RSA、SM2

仅供参考

二、代码汇总

1、编写代码

1)引入第三方库

<!-- SpringBoot或SpringCloud项目中已有此包,无需再额外引入 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.31</version>
</dependency>
<!-- 建议使用最新版本 -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
	<version>1.15</version>
</dependency>
<!-- 建议使用最新版本 -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

2)使用Java8在IDEA中实现,示例代码如下:

package com.example.base.util;


//import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
//import org.springframework.util.DigestUtils;

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

/**
 * 加密算法工具类(能用国密就用国密,免得以后因为安全问题让你改)
 * <p>
 * 1、不可逆:MD5、SHA、HMAC、SM3
 * 2.1、可逆对称:DES、AES、SM1(未公开)、SM4
 * 2.2、可逆不对称:RSA、SM2
 *
 * @author 一个不愿意透露姓名的帅比
 * @date 2024/7/13 21:01
 */
@SuppressWarnings("unused")
public class EncryptUtils {
    static {
        // 添加安全提供者(SM2,SM3,SM4等加密算法,CBC、CFB等加密模式,PKCS7Padding等填充方式,不在Java标准库中,由BouncyCastleProvider实现)
        Security.addProvider(new BouncyCastleProvider());
    }

    // -------------------------------------------------------------------------------------- 不可逆加密(无法解密,一般输出为16进制字符串)

    /**
     * MD5,信息摘要算法(Message-Digest Algorithm5),一种被广泛使用的密码散列函数,可以产生出一个固定长度的散列值。用于确保信息传输完整一致。
     * <p>
     * 输入:待加密的字符串
     * 输出:128位(16字节)或32个16进制字符(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★☆☆☆☆
     *
     * @param plainString 明文
     * @return cipherString 密文
     */
    public static String md5(String plainString) {
        // 方式1(推荐):使用spring的工具类;org.springframework.util.DigestUtils
//        return DigestUtils.md5DigestAsHex(plainString.getBytes(StandardCharsets.UTF_8));
        // 方式2:使用apache的工具类;org.apache.commons.codec.digest.DigestUtils
//        return DigestUtils.md5Hex(plainString.getBytes(StandardCharsets.UTF_8));
        // 方式3:使用Java标准库实现
        String cipherString = null;
        try {
            // 获取实例
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            // 计算摘要
            byte[] cipherBytes = messageDigest.digest(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : cipherBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * SHA256,安全散列算法(Secure Hash Algorithm 256-bit),一种被广泛使用的密码散列函数,可以产生出一个固定长度的散列值。用于确保信息传输完整一致。
     * <p>
     * 输入:待加密的字符串
     * 输出:256位(16字节)或64个16进制字符(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★☆☆☆
     *
     * @param plainString 明文
     * @return cipherString 密文
     */
    public static String sha256(String plainString) {
        // 方式1:使用apache的org.apache.commons.codec.digest.DigestUtils
//        return DigestUtils.sha256Hex(plainString.getBytes(StandardCharsets.UTF_8));
        // 方式2:使用Java标准库实现
        String cipherString = null;
        try {
            // 获取实例(SHA-512同理)
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            // 计算摘要
            byte[] cipherBytes = messageDigest.digest(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : cipherBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * SM3,国家商用密码(Shang Mi3)也称国密3,是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。
     * <p>
     * 输入:待加密的字符串
     * 输出:256位(16字节)或64个16进制字符(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★☆☆☆
     *
     * @param plainString 明文
     * @return cipherString 密文
     */
    public static String sm3(String plainString) {
        // 方式1(正式项目不推荐):使用三方组件hutool:cn.hutool.crypto.SmUtil.sm3()
//        return SmUtil.sm3(plainString);
        String cipherString = null;
        try {
            // 创建SM3Digest对象
            SM3Digest sm3Digest = new SM3Digest();
            // 初始化SM3计算
            sm3Digest.update(plainString.getBytes(StandardCharsets.UTF_8), 0, plainString.length());
            // 创建输出缓冲区
            byte[] cipherBytes = new byte[sm3Digest.getDigestSize()];
            // 计算SM3摘要
            sm3Digest.doFinal(cipherBytes, 0);
            // 输出16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : cipherBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * HMAC-MD5,Hash-based Message Authentication Code,是一种基于哈希函数和密钥的消息认证码算法,用于确保消息的完整性和认证。
     * <p>
     * 输入:待加密的字符串
     * 输出:与MD5一致
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★☆☆☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String hmacMD5(String plainString, String key) {
        String cipherString = null;
        try {
            // 指定算法
            String algorithm = "HmacMD5";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Mac对象实例
            Mac mac = Mac.getInstance(algorithm);
            // 初始化mac
            mac.init(secretKeySpec);
            // 计算mac
            byte[] macBytes = mac.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : macBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * HMAC-SHA256,Hash-based Message Authentication Code,是一种基于哈希函数和密钥的消息认证码算法,用于确保消息的完整性和认证。
     * <p>
     * 输入:待加密的字符串
     * 输出:与SHA256一致
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String hmacSHA256(String plainString, String key) {
        String cipherString = null;
        try {
            // 指定算法
            String algorithm = "HmacSHA256";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Mac对象实例
            Mac mac = Mac.getInstance(algorithm);
            // 初始化mac
            mac.init(secretKeySpec);
            // 计算mac
            byte[] macBytes = mac.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : macBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * HMAC-SM3,Hash-based Message Authentication Code,是一种基于哈希函数和密钥的消息认证码算法,用于确保消息的完整性和认证。
     * <p>
     * 输入:待加密的字符串
     * 输出:与SM3一致
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String hmacSM3(String plainString, String key) {
        String cipherString = null;
        try {
            // 创建KeyParameter对象
            KeyParameter keyParameter = new KeyParameter(key.getBytes(StandardCharsets.UTF_8));
            // 创建HMac对象
            HMac hmac = new HMac(new SM3Digest());
            // 初始化hmac
            hmac.init(keyParameter);
            // 更新hmac
            hmac.update(plainString.getBytes(StandardCharsets.UTF_8), 0, plainString.length());
            // 创建输出缓冲区
            byte[] macBytes = new byte[hmac.getMacSize()];
            // 计算hmac
            hmac.doFinal(macBytes, 0);
            // 输出为16进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : macBytes) {
                sb.append(String.format("%02x", b));
            }
            cipherString = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    // -------------------------------------------------------------------------------------- 对称加密(需要解密,一般输出为Base64编码)

    /**
     * DES,Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法。
     * <p>
     * 输入:待加密的字符串,8位字符串密码
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String desEncrypt(String plainString, String key) {
        String cipherString = null;
        try {
            // 指定算法
            String algorithm = "DES";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(Java8中DES默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * DES,Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法。
     * <p>
     * 输入:密文,8位字符串密码
     * 输出:明文字符串
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param cipherString 密文
     * @param key          秘钥
     * @return plainString 明文
     */
    public static String desDecrypt(String cipherString, String key) {
        String plainString = null;
        try {
            // 指定算法
            String algorithm = "DES";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(Java8中DES默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    /**
     * AES,Advanced Encryption Standard,即高级数据加密标准。
     * <p>
     * 输入:待加密的字符串,16或24或32位字符串密码
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String aesEncrypt(String plainString, String key) {
        String cipherString = null;
        try {
            // 指定算法
            String algorithm = "AES";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(Java8中AES默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * AES,Advanced Encryption Standard,即高级数据加密标准。
     * <p>
     * 输入:密文,16或24或32位字符串密码
     * 输出:明文
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param cipherString 密文
     * @param key          秘钥
     * @return plainString 明文
     */
    public static String aesDecrypt(String cipherString, String key) {
        String plainString = null;
        try {
            // 指定算法
            String algorithm = "AES";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(Java8中AES默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    /**
     * SM4,商业密码(Shang Mi4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布,相关标准为“GM/T 0002-2012《SM4分组密码算法》”。
     * <p>
     * 输入:待加密的字符串,16或24或32位字符串密码
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param plainString 明文
     * @param key         秘钥
     * @return cipherString 密文
     */
    public static String sm4Encrypt(String plainString, String key) {
        String cipherString = null;
        try {
            // 指定加密算法
            String algorithm = "SM4";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(BC中SM4默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * SM4,商业密码(Shang Mi4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012年3月21日发布,相关标准为“GM/T 0002-2012《SM4分组密码算法》”。
     * <p>
     * 输入:密文,16或24或32位字符串密码
     * 输出:明文
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param cipherString 密文
     * @param key          秘钥
     * @return plainString 明文
     */
    public static String sm4Decrypt(String cipherString, String key) {
        String plainString = null;
        try {
            // 指定加密算法
            String algorithm = "SM4";
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), algorithm);
            // 获取Cipher对象实例(BC中SM4默认使用ECB模式和PKCS5Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS5Padding");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    // -------------------------------------------------------------------------------------- 不对称加密(需要解密,一般输出为Base64编码)

    /**
     * 生成一组RSA的秘钥
     *
     * @param length 秘钥长度
     * @return KeyPair对象
     */
    public static KeyPair genRSAKey(int length) {
        KeyPair keyPair = null;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(length, new SecureRandom());
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return keyPair;
    }

    /**
     * RSA,三个作者的姓氏开头字母组合,RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。
     * <p>
     * 输入:待加密的字符串,公钥
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param plainString 明文
     * @param publicKey   公钥
     * @return cipherString 密文
     */
    public static String rsaEncrypt(String plainString, PublicKey publicKey) {
        String cipherString = null;
        try {
            // 获取Cipher对象实例(Java8中RSA默认使用ECB模式和PKCS1Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * RSA,三个作者的姓氏开头字母组合,RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。
     * <p>
     * 输入:待加密的字符串,公钥
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param plainString     明文
     * @param publicKeyString 公钥
     * @return cipherString 密文
     */
    public static String rsaEncrypt(String plainString, String publicKeyString) {
        String cipherString = null;
        try {
            // 指定算法
            String algorithm = "RSA";
            // 构造PublicKey对象
            publicKeyString = publicKeyString.replaceAll("-----BEGIN PUBLIC KEY-----", "")
                    .replaceAll("-----END PUBLIC KEY-----", "").replaceAll("\\s", "");
            byte[] keyBytes = Base64.getDecoder().decode(publicKeyString);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            PublicKey publicKey = keyFactory.generatePublic(keySpec);
            // 获取Cipher对象实例(Java8中RSA默认使用ECB模式和PKCS1Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS1Padding");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * RSA,三个作者的姓氏开头字母组合,RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。
     * <p>
     * 输入:16进制字符串或Base64编码的字符串密文,私钥
     * 输出:明文字符串
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param cipherString 密文
     * @param privateKey   秘钥
     * @return plainString 明文
     */
    public static String rsaDecrypt(String cipherString, PrivateKey privateKey) {
        String plainString = null;
        try {
            // 获取Cipher对象实例(Java8中RSA默认使用ECB模式和PKCS1Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    /**
     * RSA,三个作者的姓氏开头字母组合,RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。
     * <p>
     * 输入:16进制字符串或Base64编码的字符串密文,私钥
     * 输出:明文字符串
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★☆☆
     *
     * @param cipherString     密文
     * @param privateKeyString 秘钥
     * @return plainString 明文
     */
    public static String rsaDecrypt(String cipherString, String privateKeyString) {
        String plainString = null;
        try {
            // 指定算法
            String algorithm = "RSA";
            // 解码Base64字符串(通常秘钥为Base64编码)
            privateKeyString = privateKeyString.replaceAll("-----BEGIN RSA PRIVATE KEY-----", "")
                    .replaceAll("-----END RSA PRIVATE KEY-----", "")
                    .replaceAll("\\s", "");
            byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);
            // 构造PrivateKey对象
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // 获取Cipher对象实例(Java8中RSA默认使用ECB模式和PKCS1Padding填充方式,因此下列模式和填充方式无需指定)
            Cipher cipher = Cipher.getInstance(algorithm + "/ECB/PKCS1Padding");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    /**
     * 生成一组SM2的秘钥
     *
     * @return KeyPair秘钥
     */
    public static KeyPair genSM2Key() {
        KeyPair keyPair = null;
        try {
            // 创建KeyPairGenerator(指定算法为EC(椭圆曲线),指定提供者为BC(BouncyCastleProvider))
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
            // 初始化
            keyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));
            // 生成密钥
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return keyPair;
    }

    /**
     * SM2,商业密码(Shang Mi2)是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。详见百科:https://baike.baidu.com/item/SM2
     * <p>
     * 输入:待加密的字符串,公钥
     * 输出:16进制字符串或Base64编码的字符串密文(常用)
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param plainString 明文
     * @param publicKey   公钥
     * @return cipherString 密文
     */
    public static String sm2Encrypt(String plainString, PublicKey publicKey) {
        String cipherString = null;
        try {
            // 获取Cipher对象实例
            Cipher cipher = Cipher.getInstance("SM2");
            // 初始化Cipher为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));
            // 输出为Base64编码
            cipherString = Base64.getEncoder().encodeToString(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherString;
    }

    /**
     * SM2,商业密码(Shang Mi2)是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。详见百科:https://baike.baidu.com/item/SM2
     * <p>
     * 输入:16进制字符串或Base64编码的字符串密文,私钥
     * 输出:明文字符串
     * 应用:密码管理、数字签名、文件完整性校验
     * 安全性:★★★★☆
     *
     * @param cipherString 密文
     * @param privateKey   秘钥
     * @return plainString 明文
     */
    public static String sm2Decrypt(String cipherString, PrivateKey privateKey) {
        String plainString = null;
        try {
            // 获取Cipher对象实例
            Cipher cipher = Cipher.getInstance("SM2");
            // 初始化Cipher为解密模式
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 获取加密byte数组
            byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));
            // 输出为字符串
            plainString = new String(cipherBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return plainString;
    }

    public static void main(String[] args) {
        String plainString = "hello world, hello java!";
        String md5 = md5(plainString);
        System.out.println("--------------------------- md5");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + md5);

        String sha256 = sha256(plainString);
        System.out.println("--------------------------- sha256");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + sha256);

        String sm3 = sm3(plainString);
        System.out.println("--------------------------- sm3");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + sm3);

        String hmacMD5 = hmacMD5(plainString, "12345678");
        System.out.println("--------------------------- hmacMD5");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + hmacMD5);

        String hmacSHA256 = hmacSHA256(plainString, "12345678");
        System.out.println("--------------------------- hmacSHA256");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + hmacSHA256);

        String hmacSM3 = hmacSM3(plainString, "12345678");
        System.out.println("--------------------------- hmacSM3");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + hmacSM3);

        System.out.println("------------------------------------------------------");

        String desEncrypt = desEncrypt(plainString, "12345678");
        String desDecrypt = desDecrypt(desEncrypt, "12345678");
        System.out.println("--------------------------- des");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + desEncrypt);
        System.out.println("解密后: " + desDecrypt);

        String aesEncrypt = aesEncrypt(plainString, "1234567812345678");
        String aesDecrypt = aesDecrypt(aesEncrypt, "1234567812345678");
        System.out.println("--------------------------- aes");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + aesEncrypt);
        System.out.println("解密后: " + aesDecrypt);

        String sm4Encrypt = sm4Encrypt(plainString, "1234567812345678");
        String sm4Decrypt = sm4Decrypt(sm4Encrypt, "1234567812345678");
        System.out.println("--------------------------- sm4");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + sm4Encrypt);
        System.out.println("解密后: " + sm4Decrypt);

        System.out.println("------------------------------------------------------");

        KeyPair rsaKey = genRSAKey(2048);
        String rsaEncrypt = rsaEncrypt(plainString, rsaKey.getPublic());
        String rsaDecrypt = rsaDecrypt(rsaEncrypt, rsaKey.getPrivate());
        System.out.println("--------------------------- rsa");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + rsaEncrypt);
        System.out.println("解密后: " + rsaDecrypt);

        KeyPair sm2Key = genSM2Key();
        String sm2Encrypt = sm2Encrypt(plainString, sm2Key.getPublic());
        String sm2Decrypt = sm2Decrypt(sm2Encrypt, sm2Key.getPrivate());
        System.out.println("--------------------------- sm2");
        System.out.println("加密前: " + plainString);
        System.out.println("加密后: " + sm2Encrypt);
        System.out.println("解密后: " + sm2Decrypt);

        System.out.println("------------------------------------------------------");
    }
}

2、运行测试

Connected to the target VM, address: '127.0.0.1:62234', transport: 'socket'
--------------------------- md5
加密前: hello world, hello java!
加密后: 0862cb559f83edaeb04e455b413b2c1d
--------------------------- sha256
加密前: hello world, hello java!
加密后: 36fe1f0190a74297bb9f95de3e16a51c252d999895070f0a0a700bab28610254
--------------------------- sm3
加密前: hello world, hello java!
加密后: 1ac1da65f9c28ccac9fa62303d3b325d7bc180bf29e354c70d1b6662939c05d6
--------------------------- hmacMD5
加密前: hello world, hello java!
加密后: ad9f836dad01cfd6dc1e3142b50a8b6e
--------------------------- hmacSHA256
加密前: hello world, hello java!
加密后: 1cb8e22b3a1c04b4164c93b1ef391b7f6a9b5507eda06d8d8454ffc906c035ed
--------------------------- hmacSM3
加密前: hello world, hello java!
加密后: 5d3025d1296e10add5006c795fb93fbba68703521eeb2b8235bbe1fb918e68a1
------------------------------------------------------
--------------------------- des
加密前: hello world, hello java!
加密后: KNugLrX23UcBoieZhlQtpGvdQD8PGIcy/rlZt9RkL8s=
解密后: hello world, hello java!
--------------------------- aes
加密前: hello world, hello java!
加密后: 1xCFNCoW3Z6gZbiXeu1++IrZpliQTk6z3NN10ygOPHc=
解密后: hello world, hello java!
--------------------------- sm4
加密前: hello world, hello java!
加密后: ykzowxeFonA3I4Y4NozLHii3EOUD4r9SMoHw9Sv9DPI=
解密后: hello world, hello java!
------------------------------------------------------
--------------------------- rsa
加密前: hello world, hello java!
加密后: Nd8h8TqBRytMKtQbKr0Rj3XPb4hrW8zHK0rypaMo49pxsdp/o0GNGWyKxV8UETNn3DHcGZCRF0RyiQWVWl3Dz8YD0vjvr8EiznniFtUPXuZ4Tihkyzdj4kl/2aRME26cSYU+F2aJflOUZYLuf6BWEUJy4hI8z+BoxZQ7q4Gaoh1axypU8wi3eOtOu0qD6J+TDxjMQbLgfyDbbxgI+H42QShvi9sWvcMSa7og1UqjuJPBVsR6fjt8c4Ncwu3Za6QgdNGuZuOsMsMU7Fmnplh3fH3PGGRO3RlkzvWAvQG1Br3rbcwVVHUo1Xl6G9SzwqqlzyS4YqgEbuTcL1RQfxi65Q==
解密后: hello world, hello java!
--------------------------- sm2
加密前: hello world, hello java!
加密后: BM3VeU8z1QFpJhAoqRhQm4Wwh4mK6UAzuE2o1ygrBUyl8n+RCNirMTVUvQk3flCH7lIlbU16C0CGPQ1gjKsF5pNT8qe9lJuTg6DXjRFgIYX94losOIWCrmfyrh5Os5Hcya47GIY0YjpBLomTEX0hbSM2PoSPS7aMgg==
解密后: hello world, hello java!
------------------------------------------------------
Disconnected from the target VM, address: '127.0.0.1:62234', transport: 'socket'

Process finished with exit code 0

三、开发总结

1、byte[]与16进制String互转

  • byte[]转16进制String代码如下(示例):
// ------------------------------------ 如下为Java标准库
// 方式1:使用String.format
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
    sb.append(String.format("%02x", b));
}
return sb.toString();
 
// 方式2:使用BigInteger
return new BigInteger(1, bytes).toString(16);
 
// 方式3:使用DatatypeConverter
return DatatypeConverter.printHexBinary(bytes);
 
// ------------------------------------ 如下为第三方组件
// 方式4:使用Apache Commons Codec
return Hex.encodeHexString(bytes);
  • 16进制Stringbyte[]
// ------------------------------------ 如下为Java标准库
// 方式1:使用BigInteger
return new BigInteger(str, 16).toByteArray();

// 方式2: 使用DatatypeConverter
return DatatypeConverter.parseHexBinary(str);

// ------------------------------------ 如下为第三方组件
// 方式3:使用Apache Commons Codec
return Hex.decodeHex(str.toCharArray());

2、BC包的用处

添加安全提供者,SM2,SM3,SM4等加密算法,CBC、CFB等加密模式,PKCS7Padding等填充方式,不在Java标准库中,由BouncyCastleProvider实现。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了常用的加密算法在Java中的实现方式,水平有限,难免出错,仅供参考,不喜勿喷,感谢!更多内容请百度和ChatGPT!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值