java 国密SM4加密

因为碰到以下问题
1.“No such algorithm: SM4/EBC/PKCS5Padding”
2.“No such provider: BC”
所以这里用的不是最新jar包加解密的

这个放在pom.xml的最上面,避免jar重复引用导致的冲突,因为重复引用的冲突也会体现上面两种情况
  <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.68</version>
        </dependency>
public class SM4Encryption {
    public static void main(String[] args) throws Exception {
        // 明文和密钥
        String plaintext = "oZNVU5Ywv-RWVgCpZGYKw9OP0WL8";
        // 加密
        String encryptedHex = encrypt(plaintext);
        System.out.println("加密结果: " + encryptedHex);

        // 解密
        String decryptedData = decrypt(encryptedHex);
        System.out.println("解密结果: " + decryptedData);
    }

    /**
     * 秘钥key
     */
    private static final String _KEY = "3MF_%dxSH%R9VPsC";

    /**
     * 加密
     *
     * @param plaintext 明文
     * @return 密文
     * @throws Exception 异常
     */
    public static String encrypt(String plaintext) throws Exception {
        byte[] keyBytes = _KEY.getBytes(StandardCharsets.UTF_8);
        keyBytes = Arrays.copyOf(keyBytes, 16);
        byte[] encryptedData = encryptSM4(plaintext, keyBytes);

        return bytesToHex(encryptedData);
    }

    /**
     * 解密
     *
     * @param encryptedData 密文
     * @return 明文
     * @throws Exception 异常
     */
    public static String decrypt(String encryptedData) throws Exception {
        byte[] keyBytes = _KEY.getBytes(StandardCharsets.UTF_8);
        keyBytes = Arrays.copyOf(keyBytes, 16);
        byte[] decryptedData = decryptSM4(hexToBytes(encryptedData), keyBytes);

        return new String(decryptedData, StandardCharsets.UTF_8);
    }

    /**
     * SM4加密函数
     * @param plaintext 明文
     * @param keyBytes 密钥
     * @return 密文
     * @throws Exception 异常
     */
    private static byte[] encryptSM4(String plaintext, byte[] keyBytes) throws Exception {
        BlockCipher sm4Engine = new SM4Engine();
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(sm4Engine, new PKCS7Padding());
        cipher.init(true, new KeyParameter(keyBytes));

        byte[] input = plaintext.getBytes(StandardCharsets.UTF_8);
        byte[] encrypted = new byte[cipher.getOutputSize(input.length)];
        int len = cipher.processBytes(input, 0, input.length, encrypted, 0);
        len += cipher.doFinal(encrypted, len);  // 确保获取完整加密数据

        return Arrays.copyOf(encrypted, len);  // 返回有效的加密数据
    }

    /**
     * SM4解密函数
     * @param encryptedData 密文
     * @param keyBytes 密钥
     * @return 明文
     * @throws Exception 异常
     */
    private static byte[] decryptSM4(byte[] encryptedData, byte[] keyBytes) throws Exception {
        BlockCipher sm4Engine = new SM4Engine();
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(sm4Engine, new PKCS7Padding());
        cipher.init(false, new KeyParameter(keyBytes));

        byte[] decrypted = new byte[cipher.getOutputSize(encryptedData.length)];
        int len = cipher.processBytes(encryptedData, 0, encryptedData.length, decrypted, 0);
        len += cipher.doFinal(decrypted, len);  // 确保获取完整解密数据

        return Arrays.copyOf(decrypted, len);  // 返回有效的解密数据
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');  // 补零,确保每个字节都是两位
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * 将十六进制字符串转换为字节数组
     * @param hex 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexToBytes(String hex) {

        if (hex.length() % 2 != 0) {
            throw new IllegalArgumentException("Invalid hexadecimal string");
        }

        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i += 2) {
            bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }

        return bytes;
    }
}
点击阅读全文
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐