首页 > 编程语言 >Java实现常用加密算法-SM4

Java实现常用加密算法-SM4

时间:2024-11-11 21:08:30浏览次数:4  
标签:Java String SM4 Cipher static key import 加密算法

参考博客:https://blog.csdn.net/m0_46713218/article/details/143099878

参考博客:sm4前后端加密集成

pom:

<!-- SM4加密依赖包 -->
<dependency>
   <groupId>org.bouncycastle</groupId>
   <artifactId>bcprov-jdk18on</artifactId>
   <version>1.78.1</version>
</dependency>

SM4加解密工具类:

package com.test.encrypt;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

/**
 * @description com.test.encrypt
 * @author: chengyu
 * @date: 2024-11-11 19:34
 */
public class EncryptUtils {

    /**
     * 指定加密算法
     */
    private static final String ALGORITHM_NAME = "SM4";

    /**
     * BC中SM4默认使用ECB模式和PKCS5Padding填充方式
     */
    private static final String ALGORITHM_ECB_PKCS5PADDING = "SM4/ECB/PKCS5Padding";

    /**
     * SM4算法目前只支持128位(即密钥16字节)
     */
    private static final int DEFAULT_KEY_SIZE = 128;

    static {
        // 防止内存中出现多次BouncyCastleProvider的实例
        if (null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    /**
     * 生成密钥
     * <p>建议使用org.bouncycastle.util.encoders.Hex将二进制转成HEX字符串</p>
     *
     * @return 密钥16位
     * @throws Exception 生成密钥异常
     */
    public static String generateKey() throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(DEFAULT_KEY_SIZE, new SecureRandom());
        return Hex.toHexString(kg.generateKey().getEncoded());
    }

    /**
     * SM4对称加解密  加密
     *
     * @param plainString 待加密的字符串
     * @param key  密钥
     * @return  密文
     */
    public static String sm4Encrypt(String plainString, String key) {
        String cipherString = null;
        try {
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(hexStringToBytes(key), ALGORITHM_NAME);
            // 获取Cipher对象实例
            Cipher cipher = Cipher.getInstance(ALGORITHM_ECB_PKCS5PADDING, BouncyCastleProvider.PROVIDER_NAME);
            // 初始化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对称加解密 解密
     * @param cipherString  密文
     * @param key   密钥
     * @return  明文
     */
    public static String sm4Decrypt(String cipherString, String key) {
        String plainString = null;
        try {
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(hexStringToBytes(key), ALGORITHM_NAME);
            // 获取Cipher对象实例
            Cipher cipher = Cipher.getInstance(ALGORITHM_ECB_PKCS5PADDING, BouncyCastleProvider.PROVIDER_NAME);
            // 初始化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;
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (hexString != null && !hexString.equals("")) {
            hexString = hexString.toUpperCase();
            if (hexString.length() % 2 != 0) {
                hexString = "0" + hexString;
            }

            int length = hexString.length() / 2;
            char[] hexChars = hexString.toCharArray();
            byte[] d = new byte[length];

            for(int i = 0; i < length; ++i) {
                int pos = i * 2;
                d[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
            }

            return d;
        } else {
            return null;
        }
    }

    private static byte charToByte(char c) {
        return (byte)"0123456789ABCDEF".indexOf(c);
    }
}

 

测试类:

package com.test.encrypt;

import java.util.Locale;

/**
 * @description com.test.encrypt
 * @author: chengyu
 * @date: 2024-11-11 19:32
 */
public class TestSm4 {

    /**
     * 默认国密sm4 key值,128bit=32位16进制字符串
     */
    public static final String SM4_HEX_KEY_NJTK = "A7C9D1A8D93E6CFD7A175D1505598B1E";

    public static void main(String[] args) throws Exception {
        String key = EncryptUtils.generateKey().toUpperCase();
        System.out.println("生成的密钥key: " + key);

        String data = "P1sw@d4Dw";
        String encrypt = EncryptUtils.sm4Encrypt(data, SM4_HEX_KEY_NJTK);
        System.out.println("使用SM4开源包加密后:" + encrypt);
        String decrypt = EncryptUtils.sm4Decrypt(encrypt, SM4_HEX_KEY_NJTK);
        System.out.println("使用SM4开源包解密后:" + decrypt);

        String decrypt2 = AlgUtil.decryptBySm4(SM4_HEX_KEY_NJTK, encrypt);
        System.out.println("使用SM4 KL包解密后:" + decrypt2);
    }


}

 

 

--

标签:Java,String,SM4,Cipher,static,key,import,加密算法
From: https://www.cnblogs.com/tenWood/p/18540581

相关文章

  • 基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现四
    一、前言介绍:免费获取:猿来入此1.1项目摘要随着信息技术的飞速发展和互联网的普及,教育领域正经历着深刻的变革。传统的面对面教学模式逐渐受到挑战,而在线课程学习教育系统作为一种新兴的教育形式,正逐渐受到广泛关注和应用。在线课程学习教育系统的出现,不仅为学生提供了更加灵......
  • Java毕设项目案例实战II基于Java+Spring Boot+MySQL的狱内罪犯危险性评估系统设计与实
    目录一、前言二、技术介绍三、系统实现四、核心代码五、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。一、前言在司法体系中,狱内罪犯的危险性评估是确保监狱安全、提升管理效率的关键环节。传统......
  • 【JAVA基础】JAVA中是值传递还是引用传递?
    JAVA中是值传递还是引用传递?基本数据类型的值传递引用类型的值传递在Java中,参数传递实际上是通过值传递(pass-by-value)来实现的,但这一点在理解时可能会因为对象的存在而显得有些复杂。为了详细解释这一点,我们需要区分基本数据类型(如int,char,boolean等)和引用类型(如......
  • 【开源免费】基于SpringBoot+Vue.JS美发门店管理系统(JAVA毕业设计)
    博主说明:本文项目编号T069,文末自助获取源码\color{red}{T069,文末自助获......
  • 【开源免费】基于SpringBoot+Vue.JS课程答疑系统(JAVA毕业设计)
    博主说明:本文项目编号T070,文末自助获取源码\color{red}{T070,文末自助获......
  • [1837]基于JAVA的森林清理智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的森林清理智慧管理系统的设计与实现指导老师(一)选题的背景和意义选题背景与意义:随着我国生态文明建设的不断深化,森林资源保护和管理的重要性日益凸显。传统的森林管理工作大多依赖人工巡查、记录和处理,存在效率低......
  • [1831]基于JAVA的森林器械智慧管理系统的设计与实现
    毕业设计(论文)开题报告表姓名学院专业班级题目基于JAVA的森林器械智慧管理系统的设计与实现指导老师(一)选题的背景和意义在当今社会,随着物联网、大数据和人工智能等先进技术的快速发展,智慧化管理已成为各行各业提升效率、优化资源分配的重要手段。在林业领域,森林器械的有......
  • 基于ssm4S店预约保养系统
    身处网络时代,随着网络系统体系发展的不断成熟和完善,人们的生活也随之发生了很大的变化,人们在追求较高物质生活的同时,也在想着如何使自身的精神内涵得到提升,而读书就是人们获得精神享受非常重要的途径。为了满足人们随时随地只要有网络就可以看书的要求,4S店预约保养系统被开......
  • JavaScript on html
    我咋没发啊,丢草稿箱里给忘了,发一下好像早就写了首先你要会一点html一点都不会建议学了再来Vscode自带html+JS自动补全,比较好用不会运行JS建议多动脑子调用可以用<script>调用也可以以字符串形式写在超链接的地方弱类型语言,变量用var定义(=new()格式下可以不......
  • java小课设:使用MySQL做一个聊天室
    bro是个懒狗,耗时一个晚上,只写了一些基础功能,其他的可以根据需要自己添加实现思路:在MySQL数据库中设置一个message表,用来存储聊天信息,聊天界面输入的内容写入message表,用户程序每秒从MySQL中获取一次聊天记录,并加载进入自己的页面,实现聊天室。食用方法:ChatServer类中的数据......