Java实现SM4加密+Base64编码完整方案

Java实现SM4加密+Base64编码完整方案

1. 实现思路

要实现「先SM4加密,再Base64编码」的流程,需要:

  1. 使用Bouncy Castle的SM4加密算法
  2. 对加密后的字节数组进行Base64编码
  3. 确保密钥和IV符合SM4规范(16字节)

2. 完整代码实现

(1)SM4+Base64工具类

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.util.Base64;

public class Sm4WithBase64Util {
    
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 生成SM4密钥(16字节)
     */
    public static byte[] generateSm4Key() throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance("SM4", "BC");
        kg.init(128); // 128位密钥
        return kg.generateKey().getEncoded();
    }

    /**
     * SM4加密 + Base64编码
     * @param plainText 明文
     * @param keyBytes  16字节密钥
     * @param ivBytes   16字节初始化向量
     * @return Base64编码后的密文
     */
    public static String encryptWithBase64(String plainText, byte[] keyBytes, byte[] ivBytes) throws Exception {
        // 1. 初始化SM4加密器(CBC模式)
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        // 2. 执行SM4加密
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));

        // 3. 对加密结果进行Base64编码
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * Base64解码 + SM4解密
     */
    public static String decryptWithBase64(String base64CipherText, byte[] keyBytes, byte[] ivBytes) throws Exception {
        // 1. Base64解码
        byte[] encryptedBytes = Base64.getDecoder().decode(base64CipherText);

        // 2. 初始化SM4解密器
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        // 3. 执行解密
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes, "UTF-8");
    }
}

(2)使用示例

public class Main {
    public static void main(String[] args) throws Exception {
        // 1. 准备密钥和IV(实际项目应使用安全随机生成)
        byte[] key = "0123456789abcdef".getBytes(); // 16字节密钥
        byte[] iv = "1234567890abcdef".getBytes();   // 16字节IV
        
        String originalText = "需要加密的敏感数据";

        // 2. 加密+Base64编码
        String encrypted = Sm4WithBase64Util.encryptWithBase64(originalText, key, iv);
        System.out.println("加密结果(Base64): " + encrypted);

        // 3. Base64解码+解密
        String decrypted = Sm4WithBase64Util.decryptWithBase64(encrypted, key, iv);
        System.out.println("解密结果: " + decrypted);
    }
}

输出示例:

加密结果(Base64): 5f4d6e3a8b7c9d0e1f2a3b4c5d6e7f8+ABcdEfGHijKlMnOp==
解密结果: 需要加密的敏感数据

3. 关键点说明

  1. 密钥和IV要求

    • 必须为16字节(128位)
    • 实际项目应使用SecureRandom生成随机值
    SecureRandom random = new SecureRandom();
    byte[] iv = new byte[16];
    random.nextBytes(iv);
    
  2. 编码选择

    • 使用Base64.getEncoder()标准编码(无换行)
    • 如需URL安全版本,可用Base64.getUrlEncoder()
  3. 异常处理

    • 需处理InvalidKeyExceptionIllegalBlockSizeException等异常
  4. 性能优化

    • 可复用Cipher实例(线程不安全,需配合ThreadLocal)

4. 完整流程图示

原始报文 → SM4加密(二进制) → Base64编码 → 最终密文

5. 生产环境建议

  1. 密钥管理

    • 使用KeyStore或HSM(硬件安全模块)存储密钥
    • 避免硬编码密钥
  2. 增强安全性

    // 推荐的安全随机生成方式
    KeyGenerator kg = KeyGenerator.getInstance("SM4");
    kg.init(256, new SecureRandom()); // 使用强随机源
    
  3. 完整校验

    • 可结合SM3对原始数据生成摘要,确保完整性

你可能感兴趣的:(java,开发语言)