前言

平时的工作中,我们在很多地方用到了加密、解密,比如:用户的密码不能明文存储,要存储加密后的密文,用户的银行卡号、身份证号和数据金额之类的敏感数据,需要加密传输,还有一些重要接口,比如支付,客户端要对请求生成一个签名,服务端要对签名进行验证……
上面提到的这些能力,我们都需要利用加密算法来实现


常见加密算法

JAVA常见加密算法


算法工具类

我整理了一些常用的算法工具类,具体内容见下

DES

DesUtil

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class DesUtil {
    private static final String DES_ALGORITHM = "DES";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文
     * @throws Exception
     */
    public static byte[] desEncryptToBytes(String content, String encryptKey) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(encryptKey.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
        SecretKey key = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(DES_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 解密
     *
     * @param content     待解密内容
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String desDecryptByBytes(byte[] content, String decryptKey) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(decryptKey.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
        SecretKey key = keyFactory.generateSecret(desKeySpec);
        Cipher cipher = Cipher.getInstance(DES_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] result = cipher.doFinal(content);
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文(Base64编码)
     * @throws Exception
     */
    public static String desEncrypt(String content, String encryptKey) throws Exception {
        byte[] encryptBytes = desEncryptToBytes(content, encryptKey);
        return base64Encode(encryptBytes);
    }

    /**
     * 解密
     *
     * @param content     待解密内容(Base64编码)
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String desDecrypt(String content, String decryptKey) throws Exception {
        byte[] decryptBytes = base64Decode(content);
        return desDecryptByBytes(decryptBytes, decryptKey);
    }
}

AES

AesUtil

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;


public class AesUtil {
    private static final String AES_ALGORITHM = "AES";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文
     * @throws Exception
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
        SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 解密
     *
     * @param content     待解密内容
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String aesDecryptByBytes(byte[] content, String decryptKey) throws Exception {
        SecretKeySpec key = new SecretKeySpec(decryptKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] result = cipher.doFinal(content);
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文(Base64编码)
     * @throws Exception
     */
    public static String aesEncrypt(String content, String encryptKey) throws Exception {
        byte[] encryptBytes = aesEncryptToBytes(content, encryptKey);
        return base64Encode(encryptBytes);
    }

    /**
     * 解密
     *
     * @param content     待解密内容(Base64编码)
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String aesDecrypt(String content, String decryptKey) throws Exception {
        byte[] decryptBytes = base64Decode(content);
        return aesDecryptByBytes(decryptBytes, decryptKey);
    }
}

Blowfish

BlowfishUtil

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class BlowfishUtil {
    private static final String BLOWFISH_ALGORITHM = "Blowfish";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文
     * @throws Exception
     */
    public static byte[] blowfishEncryptToBytes(String content, String encryptKey) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(encryptKey.getBytes(StandardCharsets.UTF_8), BLOWFISH_ALGORITHM);
        Cipher cipher = Cipher.getInstance(BLOWFISH_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 解密
     *
     * @param content     待解密内容
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String blowfishDecryptByBytes(byte[] content, String decryptKey) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(decryptKey.getBytes(StandardCharsets.UTF_8), BLOWFISH_ALGORITHM);
        Cipher cipher = Cipher.getInstance(BLOWFISH_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] result = cipher.doFinal(content);
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param encryptKey  加密密钥
     * @return 加密后的密文(Base64编码)
     * @throws Exception
     */
    public static String blowfishEncrypt(String content, String encryptKey) throws Exception {
        byte[] encryptBytes = blowfishEncryptToBytes(content, encryptKey);
        return base64Encode(encryptBytes);
    }

    /**
     * 解密
     *
     * @param content     待解密内容(Base64编码)
     * @param decryptKey  解密密钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String blowfishDecrypt(String content, String decryptKey) throws Exception {
        byte[] decryptBytes = base64Decode(content);
        return blowfishDecryptByBytes(decryptBytes, decryptKey);
    }
}

RSA

RSAUtil

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

public class RSAUtil {
    private static final String RSA_ALGORITHM = "RSA";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 加密
     *
     * @param content     待加密内容
     * @param publicKey   公钥
     * @return 加密后的密文(Base64编码)
     * @throws Exception
     */
    public static String rsaEncrypt(String content, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptBytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return base64Encode(encryptBytes);
    }

    /**
     * 解密
     *
     * @param content     待解密内容(Base64编码)
     * @param privateKey  私钥
     * @return 解密后的明文
     * @throws Exception
     */
    public static String rsaDecrypt(String content, PrivateKey privateKey) throws Exception {
        byte[] decryptBytes = base64Decode(content);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(decryptBytes);
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 将Base64编码的公钥字符串转换为PublicKey对象
     *
     * @param publicKeyStr Base64编码的公钥字符串
     * @return PublicKey对象
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] publicKeyBytes = base64Decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 将Base64编码的私钥字符串转换为PrivateKey对象
     *
     * @param privateKeyStr Base64编码的私钥字符串
     * @return PrivateKey对象
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        byte[] privateKeyBytes = base64Decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }
}

DSA

DSAUtil

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class DSAUtil {
    private static final String DSA_ALGORITHM = "DSA";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 使用私钥对内容进行签名
     *
     * @param content      待签名内容
     * @param privateKey   私钥
     * @return 签名结果(Base64编码)
     * @throws Exception
     */
    public static String dsaSign(String content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(DSA_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = signature.sign();
        return base64Encode(signBytes);
    }

    /**
     * 使用公钥验证签名
     *
     * @param content       待验证内容
     * @param signatureStr  签名结果(Base64编码)
     * @param publicKey     公钥
     * @return 验证结果
     * @throws Exception
     */
    public static boolean dsaVerify(String content, String signatureStr, PublicKey publicKey) throws Exception {
        byte[] signatureBytes = base64Decode(signatureStr);
        Signature signature = Signature.getInstance(DSA_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        return signature.verify(signatureBytes);
    }

    /**
     * 将Base64编码的公钥字符串转换为PublicKey对象
     *
     * @param publicKeyStr Base64编码的公钥字符串
     * @return PublicKey对象
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] publicKeyBytes = base64Decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(DSA_ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 将Base64编码的私钥字符串转换为PrivateKey对象
     *
     * @param privateKeyStr Base64编码的私钥字符串
     * @return PrivateKey对象
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        byte[] privateKeyBytes = base64Decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(DSA_ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }
}

ECC

ECCUtil

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class ECCUtil {
    private static final String ECC_ALGORITHM = "EC";

    public static String base64Encode(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] base64Decode(String base64Code) {
        return Base64.getDecoder().decode(base64Code);
    }

    /**
     * 使用私钥对内容进行签名
     *
     * @param content      待签名内容
     * @param privateKey   私钥
     * @return 签名结果(Base64编码)
     * @throws Exception
     */
    public static String eccSign(String content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initSign(privateKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = signature.sign();
        return base64Encode(signBytes);
    }

    /**
     * 使用公钥验证签名
     *
     * @param content       待验证内容
     * @param signatureStr  签名结果(Base64编码)
     * @param publicKey     公钥
     * @return 验证结果
     * @throws Exception
     */
    public static boolean eccVerify(String content, String signatureStr, PublicKey publicKey) throws Exception {
        byte[] signatureBytes = base64Decode(signatureStr);
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initVerify(publicKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        return signature.verify(signatureBytes);
    }

    /**
     * 将Base64编码的公钥字符串转换为PublicKey对象
     *
     * @param publicKeyStr Base64编码的公钥字符串
     * @return PublicKey对象
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] publicKeyBytes = base64Decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ECC_ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 将Base64编码的私钥字符串转换为PrivateKey对象
     *
     * @param privateKeyStr Base64编码的私钥字符串
     * @return PrivateKey对象
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        byte[] privateKeyBytes = base64Decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ECC_ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }
}

MD5

FileMD5Util

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

@Slf4j
public class FileMD5Util {
    private static final String MD5_ALGORITHM = "MD5";

    /**
     * 计算文件的MD5哈希值
     *
     * @param file 文件对象
     * @return 计算得到的MD5哈希值的十六进制表示
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static String calculateFileMD5(File file) throws NoSuchAlgorithmException, IOException {
        try (InputStream is = new FileInputStream(file)) {
            return calculateFileMD5(is);
        } catch (IOException e) {
            log.error("Failed to calculate MD5 for file: {}", file.getAbsolutePath(), e);
            throw e;
        }
    }

    /**
     * 计算文件的MD5哈希值
     *
     * @param filePath 文件路径
     * @return 计算得到的MD5哈希值的十六进制表示
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static String calculateFileMD5(String filePath) throws NoSuchAlgorithmException, IOException {
        File file = new File(filePath);
        return calculateFileMD5(file);
    }

    /**
     * 计算文件的MD5哈希值
     *
     * @param inputStream 文件输入流
     * @return 计算得到的MD5哈希值的十六进制表示
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static String calculateFileMD5(InputStream inputStream) throws NoSuchAlgorithmException, IOException {
        MessageDigest md = MessageDigest.getInstance(MD5_ALGORITHM);
        try (DigestInputStream dis = new DigestInputStream(inputStream, md)) {
            byte[] buffer = new byte[4096];
            while (dis.read(buffer) != -1) {
                // 读取文件内容,更新消息摘要
                md.update(buffer);
            }
        }

        byte[] digest = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString();
    }

    /**
     * 校验文件的完整性
     *
     * @param file         文件对象
     * @param expectedMD5  预期的MD5哈希值(十六进制表示)
     * @return 如果实际的MD5哈希值与预期值相等(忽略大小写),返回true;否则返回false
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static boolean verifyFileIntegrity(File file, String expectedMD5)
            throws NoSuchAlgorithmException, IOException {
        try (InputStream is = new FileInputStream(file)) {
            return verifyFileIntegrity(is, expectedMD5);
        } catch (IOException e) {
            log.error("Failed to verify file integrity for file: {}", file.getAbsolutePath(), e);
            throw e;
        }
    }

    /**
     * 校验文件的完整性
     *
     * @param filePath     文件路径
     * @param expectedMD5  预期的MD5哈希值(十六进制表示)
     * @return 如果实际的MD5哈希值与预期值相等(忽略大小写),返回true;否则返回false
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static boolean verifyFileIntegrity(String filePath, String expectedMD5)
            throws NoSuchAlgorithmException, IOException {
        File file = new File(filePath);
        return verifyFileIntegrity(file, expectedMD5);
    }

    /**
     * 校验文件的完整性
     *
     * @param inputStream  文件输入流
     * @param expectedMD5  预期的MD5哈希值(十六进制表示)
     * @return 如果实际的MD5哈希值与预期值相等(忽略大小写),返回true;否则返回false
     * @throws NoSuchAlgorithmException 如果MD5算法不可用
     * @throws IOException              如果读取文件时发生I/O错误
     */
    public static boolean verifyFileIntegrity(InputStream inputStream, String expectedMD5)
            throws NoSuchAlgorithmException, IOException {
        String actualMD5 = calculateFileMD5(inputStream);
        return actualMD5.equalsIgnoreCase(expectedMD5);
    }
}

SHA-1、SHA-256、SHA-384、SHA-512

SHAUtil

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class SHAUtil {
    /**
     * 计算 SHA-1 哈希值
     *
     * @param content 待计算的内容
     * @return SHA-1 哈希值
     * @throws Exception 计算过程中的异常
     */
    public static String sha1(String content) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        byte[] hashBytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
        return bytesToHexString(hashBytes);
    }

    /**
     * 计算 SHA-256 哈希值
     *
     * @param content 待计算的内容
     * @return SHA-256 哈希值
     * @throws Exception 计算过程中的异常
     */
    public static String sha256(String content) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hashBytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
        return bytesToHexString(hashBytes);
    }

    /**
     * 计算 SHA-384 哈希值
     *
     * @param content 待计算的内容
     * @return SHA-384 哈希值
     * @throws Exception 计算过程中的异常
     */
    public static String sha384(String content) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-384");
        byte[] hashBytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
        return bytesToHexString(hashBytes);
    }

    /**
     * 计算 SHA-512 哈希值
     *
     * @param content 待计算的内容
     * @return SHA-512 哈希值
     * @throws Exception 计算过程中的异常
     */
    public static String sha512(String content) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-512");
        byte[] hashBytes = digest.digest(content.getBytes(StandardCharsets.UTF_8));
        return bytesToHexString(hashBytes);
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHexString(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();
    }
}

HMAC

HMACUtil

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class HMACUtil {
    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final String CHARSET = "UTF-8";

    /**
     * 计算 HMAC 值
     *
     * @param content   待计算的内容
     * @param secretKey 密钥
     * @return HMAC 值(Base64 编码)
     * @throws Exception 计算过程中的异常
     */
    public static String calculateHMAC(String content, String secretKey) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
        Mac mac = Mac.getInstance(HMAC_ALGORITHM);
        mac.init(keySpec);
        byte[] hmacBytes = mac.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hmacBytes);
    }
}

Last modification:November 28, 2023
如果觉得我的文章对你有用,您可以给博主买一杯果汁,谢谢!