SM4算法加密

67 阅读1分钟

描述

sm4算法类似AES算法

代码

package org.example.test;

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.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

public class SM4Test {

    static {
        Security.addProvider(new BouncyCastleProvider()); // 注册BouncyCastle
    }

    public static SecretKey generateSM4Key() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4", "BC"); // 指定算法和提供商
        keyGenerator.init(128); // SM4密钥长度固定128位
        return keyGenerator.generateKey();
    }

    public static String secretKeyStr() throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4", "BC"); // 指定算法和提供商
        keyGenerator.init(128); // SM4密钥长度固定128位
        byte[] encoded = keyGenerator.generateKey().getEncoded();
        return Base64.getEncoder().encodeToString(encoded);
    }

    public static byte[] sm4Encrypt(byte[] plaintext, SecretKey key) throws Exception {
        // 生成随机IV(16字节)
        byte[] iv = new byte[16];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

        // 加密数据(最终密文 = IV + 加密内容)
        byte[] ciphertext = cipher.doFinal(plaintext);
        return concatenateArrays(iv, ciphertext); // 将IV与密文拼接
    }

    // 工具方法:拼接两个字节数组
    private static byte[] concatenateArrays(byte[] a, byte[] b) {
        byte[] result = new byte[a.length + b.length];
        System.arraycopy(a, 0, result, 0, a.length);
        System.arraycopy(b, 0, result, a.length, b.length);
        return result;
    }


    public static byte[] sm4Decrypt(byte[] ciphertextWithIv, SecretKey key) throws Exception {
        // 分离IV和密文(前16字节是IV)
        byte[] iv = new byte[16];
        byte[] ciphertext = new byte[ciphertextWithIv.length - 16];
        System.arraycopy(ciphertextWithIv, 0, iv, 0, 16);
        System.arraycopy(ciphertextWithIv, 16, ciphertext, 0, ciphertext.length);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 初始化解密器
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

        // 解密数据
        return cipher.doFinal(ciphertext);
    }


    public static void main(String[] args) throws Exception {
        // 生成密钥
       // SecretKey key = generateSM4Key();
        String keyStr = secretKeyStr();

        SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(keyStr),"SM4");


        // 加密测试数据
        String originalText = "Hello, SM4!";
        byte[] encrypted = sm4Encrypt(originalText.getBytes("UTF-8"), key);

        // 解密验证
        byte[] decrypted = sm4Decrypt(encrypted, key);
        String result = new String(decrypted, "UTF-8");

        System.out.println("原文: " + originalText);
        System.out.println("解密结果: " + result); // 应输出 "Hello, SM4!"
    }
}