JAVA集成国密SM3

这篇具有很好参考价值的文章主要介绍了JAVA集成国密SM3。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527

SM3杂凑算法
SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。

一、pom配置

<!-- 国密 -->
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15to18</artifactId>
	<version>1.66</version>
</dependency>

<!-- 验签 -->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.4.5</version>
</dependency>

二、加密代码集成

2.1、目录结构

java sm3,国密,SpringBoot,java,开发语言

2.2、源码

SecretCommon.java

package com.secret.sm3;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

/**
 * SM3密码杂凑算法(哈希算法)
 * SM3杂凑算法是我国自主设计的密码杂凑算法。
 * 适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。
 * 为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短。
 * 例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。
 */
public class SecretCommon {

    /**
     * sm3算法加密,不可逆加密
     * @param plainText 需加密的明文字符串
     * @return 加密后固定长度64的16进制字符串
     */
    public static String encrypt(String plainText) {
        return ByteUtils.toHexString(encrypt(plainText.getBytes()));
    }

    /**
     * sm3算法加密,不可逆加密
     * @param plainByte 需加密的明文数组
     * @return 加密后固定长度64的16进制数组
     */
    public static byte[] encrypt(byte[] plainByte) {
        SM3Digest sm3Digest = new SM3Digest();
        sm3Digest.update(plainByte, 0, plainByte.length);
        byte[] digestByte = new byte[sm3Digest.getDigestSize()];
        sm3Digest.doFinal(digestByte, 0);
        return digestByte;
    }

    /**
     * sm3算法通过密钥进行加密,不可逆加密
     * @param keyText 密钥字符串
     * @param plainText 需加密的明文字符串
     * @return 加密后固定长度64的16进制字符串
     */
    public static String encryptByKey(String keyText, String plainText) {
        return ByteUtils.toHexString(encryptByKey(keyText.getBytes(), plainText.getBytes()));
    }

    /**
     * sm3算法通过密钥进行加密,不可逆加密
     * @param keyByte 密钥数组
     * @param plainByte 需加密的明文数组
     * @return 加密后固定长度64的16进制数组
     */
    public static byte[] encryptByKey(byte[] keyByte, byte[] plainByte) {
        KeyParameter keyParameter = new KeyParameter(keyByte);
        SM3Digest sm3Digest = new SM3Digest();
        HMac hMac = new HMac(sm3Digest);
        hMac.init(keyParameter);
        hMac.update(plainByte, 0, plainByte.length);
        byte[] result = new byte[hMac.getMacSize()];
        hMac.doFinal(result, 0);
        return result;
    }

}

Utils.java

package com.secret.sm3;

public class Utils {

    /**
     * sm3算法加密,不可逆加密
     * @param plainText 需加密的明文字符串
     * @return 加密后固定长度64的16进制字符串
     */
    public static String encrypt(String plainText) {
        return SecretCommon.encrypt(plainText);
    }

    /**
     * sm3算法通过密钥进行加密,不可逆加密
     * @param keyByte 密钥字符串
     * @param plainText 需加密的明文字符串
     * @return 加密后固定长度64的16进制字符串
     */
    public static String encryptByKey(String keyText, String plainText) {
        return SecretCommon.encryptByKey(keyText, plainText);
    }

}

测试类:Test.java

package com.secret.sm3;

public class Test {

    public static void main(String[] args) {
        System.out.println("SM3加密:" + Utils.encrypt("I believe you can do anything"));
        System.out.println("SM3秘钥加密:" + Utils.encryptByKey("myKey", "Do what you want to do"));
    }

}

2.3、测试

java sm3,国密,SpringBoot,java,开发语言
使用方法参考测试类即可。

三、验签代码集成

2.1、目录结构

java sm3,国密,SpringBoot,java,开发语言

2.2、源码

SignatureCommon.java

package com.secret.sm3.signature;

import cn.hutool.crypto.SmUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SignatureCommon {

    private static Logger log = LoggerFactory.getLogger(SignatureCommon.class);

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     */
    public static boolean checkSignJson(String sign, Object object, String privateKey, Long timestamp)  {
        return checkSignJson(sign, object, privateKey, timestamp, SignatureConstant.SIGNATURE_VALIDITY_TIME);
    }

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     * @param validityTime 校验时间,单位分钟
     */
    public static boolean checkSignJson(String sign, Object object, String privateKey, Long timestamp, Integer validityTime)  {
        //关闭验签,默认TRUE
        if(!SignatureConstant.SIGNATURE_SWITCH) return true;
        if(!checkTime(timestamp, validityTime)) return false;
        String localSign = getSign(new SignatureStrategyJson().getSignValue(object, privateKey, timestamp));
        return localSign.toUpperCase().equals(sign.toUpperCase());
    }

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     */
    public static boolean checkSignArray(String sign, Object object, String privateKey, Long timestamp) {
        return checkSignArray(sign, object, privateKey, timestamp, SignatureConstant.SIGNATURE_VALIDITY_TIME);
    }

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     * @param validityTime 校验时间,单位分钟
     */
    public static boolean checkSignArray(String sign, Object object, String privateKey, Long timestamp, Integer validityTime) {
        //关闭验签,默认TRUE
        if(!SignatureConstant.SIGNATURE_SWITCH) return true;
        if(!checkTime(timestamp, validityTime)) return false;
        String localSign = getSign(new SignatureStrategyArray().getSignValue(object, privateKey, timestamp));
        return localSign.toUpperCase().equals(sign.toUpperCase());
    }

    /**
     * 加密签名
     * @param signValue 待加密签名字符串
     * @return 加密后签名字符串
     */
    public static String getSign(String signValue){
        return SmUtil.sm3(signValue);
    }

    /**
     * 校验时间范围
     * @param timestamp 页面时间
     */
    public static boolean checkTime(Long timestamp, Integer validityTime) {
        Long nowTime = System.currentTimeMillis();
        Long difference = nowTime - timestamp;
        //配置时间大于0,则验证时间戳,在时间范围内才处理
        if (validityTime > 0){
            if(difference >= 60000 * validityTime || difference <= 0){
                log.error("时间戳异常,非" + validityTime + "分钟内请求,当前时间戳:" + nowTime);
                return false;
            }
        }
        return true;
    }

}

SignatureConstant.java

package com.secret.sm3.signature;

public class SignatureConstant {

    public static final Boolean SIGNATURE_SWITCH = true; //请求签名开关

    @Deprecated
    public static final Boolean SIGNATURE_SWITCH_TRUE = true; //请求签名开

    @Deprecated
    public static final Boolean SIGNATURE_SWITCH_FALSE = false; //请求签名关

    public static final Integer SIGNATURE_VALIDITY_TIME = 1; //请求签名有效时间 默认1分钟

}

SignatureStrategy.java

package com.secret.sm3.signature;

public interface SignatureStrategy {

    String getSignValue(Object object);

    String getSignValue(Object object, String privateKey, Long timestamp);

}

SignatureStrategyArray.java

package com.secret.sm3.signature;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;

public class SignatureStrategyArray implements SignatureStrategy {

    private static Logger log = LoggerFactory.getLogger(SignatureStrategyArray.class);

    @Override
    public String getSignValue(Object object, String privateKey, Long timestamp) {
        return getSignValue(object) + "&privateKey=" + privateKey + "&timestamp=" + timestamp;
    }

    /**
     * 获取实体类拼成的加密字段
     * @param object 参数实体类
     * @return 待加密字符串
     */
    @Override
    public String getSignValue(Object object) {
        Field[] fields = object.getClass().getDeclaredFields();//获取所有属性
        String[][] fieldArray = new String[fields.length][2]; //用二维数组保存  参数名和参数值
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            fieldArray[i][0] = fields[i].getName().toLowerCase(); //获取属性名
            try {
                fieldArray[i][1] = String.valueOf(fields[i].get(object)); //把属性值放进数组
            } catch (IllegalAccessException e) {
                log.error("signature field:" + fields[i].getName() + "Failed to add value");
            }
        }
        fieldArray = doChooseSort(fieldArray); //对参数实体类按照字母顺序排续
        StringBuilder result = new StringBuilder();
        for (String[] field : fieldArray) {//按照签名规则生成待加密字符串
            result.append(field[0]).append("=").append(field[1]).append("&");
        }
        result = new StringBuilder(result.substring(0, result.length() - 1));//消除掉最后的“&”
        log.info("signature Information:" , result.toString());
        return result.toString();
    }

    /**
     * 对二维数组里面的数据进行选择排序,按字段名按abcd顺序排列
     * @param data 未按照字母顺序排序的二维数组
     */
    private String[][] doChooseSort(String[][] data) {//排序方式为选择排序
        int n = data.length;
        for (int i = 0; i < n - 1; i++) {
            int k = i; // 初始化最小值的小标
            for (int j = i + 1; j < n; j++) {
                if (data[k][0].compareTo(data[j][0]) > 0) { //下标k字段名大于当前字段名
                    k = j;// 修改最大值的小标
                }
            }
            // 将最小值放到排序序列末尾
            if (k > i) { //用相加相减法交换data[i] 和 data[k]
                String tempValue ;
                tempValue = data[k][0];
                data[k][0] = data[i][0];
                data[i][0] = tempValue;
                tempValue = data[k][1];
                data[k][1] = data[i][1];
                data[i][1] = tempValue;
            }
        }
        return data;
    }

}

SignatureStrategyJson.java

package com.secret.sm3.signature;

import cn.hutool.json.JSONUtil;

public class SignatureStrategyJson implements SignatureStrategy {

    @Override
    public String getSignValue(Object object, String privateKey, Long timestamp) {
        return getSignValue(object) + "&privateKey=" + privateKey + "&timestamp=" + timestamp;
    }

    /**
     * 获取实体类拼成的加密字段
     * @param object  传入参数实体类
     * @return  待加密字符串
     */
    public String getSignValue(Object object) {
        return JSONUtil.toJsonStr(object);
    }

}

Utils.java

package com.secret.sm3.signature;

public class Utils {

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     */
    public static boolean checkSign(String sign, Object object, String privateKey, Long timestamp)  {
        return SignatureCommon.checkSignJson(sign, object, privateKey, timestamp);
    }

    /**
     * 验签(JSON方式,较简单)
     * @param sign 前端传入签名(可从请求报文头获取)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳(可从请求报文头获取)
     * @param validityTime 校验时间,单位分钟
     */
    public static boolean checkSign(String sign, Object object, String privateKey, Long timestamp, Integer validityTime)  {
        return SignatureCommon.checkSignJson(sign, object, privateKey, timestamp, validityTime);
    }

    /**
     * 获取签名(JSON方式,较简单)
     * @param object 传输实体模型
     * @param privateKey 签名加密私钥
     * @param timestamp 时间戳
     */
    public static String getSignValue(Object object, String privateKey, Long timestamp) {
        return SignatureCommon.getSign(new SignatureStrategyJson().getSignValue(object, privateKey, timestamp));
    }

}

测试类:TestBean.java

package com.secret.sm3.signature;

public class TestBean {
    private String name;
    private String idCard;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getIdCard() {
        return idCard;
    }
    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }
    public TestBean() {

    }
    public TestBean(String name, String idCard) {
        this.name = name;
        this.idCard = idCard;
    }

}

测试类:Test.java

package com.secret.sm3.signature;

public class Test {

    public static void main(String[] args) throws Exception {
        //模拟请求
        TestBean bean = new TestBean("张三", "532143200009129565");
        Long nowTime = System.currentTimeMillis();
        String privateKey = "143s57a7b60841c2";

        String errorSign = "Today is really a beautiful day";
        System.out.println("一.错误签名示例,验签结果:" + Utils.checkSign(errorSign, bean, privateKey, nowTime));

        //2.签名、时间均正确的示例
        String rightSign = Utils.getSignValue(bean, privateKey, nowTime);
        System.out.println("二.正确签名示例,验签结果:" + Utils.checkSign(rightSign, bean, privateKey, nowTime));

        //3.签名正确,时间错误的示例
        Long oldTime = 1672502400000L; //示例时间:2023-01-01 00:00:00
        System.out.println("三.错误时间示例,验签结果:" + Utils.checkSign(rightSign, bean, privateKey, oldTime));
    }

}

2.3、测试

java sm3,国密,SpringBoot,java,开发语言
使用方法参考测试类即可。

四、相关链接

国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527

JAVA集成国密SM2:https://blog.csdn.net/qq_38254635/article/details/131810661

JAVA集成国密SM4:https://blog.csdn.net/qq_38254635/article/details/131810715文章来源地址https://www.toymoban.com/news/detail-730950.html

到了这里,关于JAVA集成国密SM3的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用 Java Bouncy Castle实现国密算法SM4、SM3以及SM2的加密

    国密算法的实现借助了Java库函数 Bouncy Castle,加密库安装使用教程请参考链接 SM4,又称为商密算法,是一种分组密码算法,于2012年由中国密码技术研究中心(中国密码学会成员)发布,目前已成为我国国家密码算法,并在多个领域得到了广泛的应用。SM4算法采用了32轮迭代结

    2024年02月16日
    浏览(30)
  • 国密SM2/SM3算法

    分类 1、SM1是一种分组加密算法 对称加密算法中的分组加密算法,其分组长度、秘钥长度都是128bit,算法安全保密强度跟 AES 相当,但是算法不公开,仅以IP核的形式存在于芯片中,需要通过加密芯片的接口进行调用。 采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙

    2024年02月05日
    浏览(50)
  • 国密SM3杂凑算法

    在了解SM3算法之前,我们有必要了解一下单向散列函数。 单向散列函数 (one-way hash function)有很多名字:压缩函数、收缩函数、 消息摘要 、指纹、密码校验和、信息完整性检验(Message Integrity Check,MIC)、操作检验码(Manipulation Detection Code,MDC)。不管你怎么叫,它都是现

    2023年04月18日
    浏览(38)
  • 国密算法SM2、SM3的使用

    1. SM2是非对称加密算法         它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号发布。 2.SM3是一种密码杂凑

    2024年02月06日
    浏览(35)
  • Go实现国密算法SM2、SM3、SM4

    SM2椭圆曲线公钥密码算法 Public key cryptographic algorithm SM2 based on elliptic curves 遵循的SM2标准号为: GM/T 0003.1-2012、GM/T 0003.2-2012、GM/T 0003.3-2012、GM/T 0003.4-2012、GM/T 0003.5-2012、GM/T 0009-2012、GM/T 0010-2012 依赖包: github.com/tjfoc/gmsm/sm2 SM3密码杂凑算法 - SM3 cryptographic hash algorithm 遵循的SM

    2024年02月15日
    浏览(31)
  • vue中使用国密算法SM2、SM3、SM4

    gm-crypto相关文档:https://gitcode.net/mirrors/byte-fe/gm-crypto?utm_source=csdn_github_accelerator vue3+element ui例子:https://gitee.com/huanglgln/vue-sys-manage-el  vue3+view ui例子:https://gitee.com/huanglgln/vue-sys-manage  vue3+Ant Design Vue ui例子:https://gitee.com/huanglgln/vue-sys-manage-adv 

    2024年02月15日
    浏览(28)
  • 前端国密加解密使用方法SM2、SM3、SM4

       国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。      不多废话直接上干货 项目中 可能存在

    2023年04月09日
    浏览(30)
  • vue普通加密以及国密SM2、SM3、sm4的使用

    sm-crypto:https://www.npmjs.com/package/sm-crypto 1. SM2是非对称加密算法 它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号

    2023年04月09日
    浏览(26)
  • Python实现国家商用密码算法sm2/sm3/sm4/sm9(国密)

    2010 年开始,我国国家密码管理局就已经开始陆续发布了一系列国产加密算法,这其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。SM1 和 SM7 的算法不公开,其余算法都已成为 ISO/IEC

    2024年02月15日
    浏览(25)
  • OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)

    openssl 3 默认废弃了 旧版本 (opessl 1.x) 的部分api 导致部分旧ecc 代码无法使用(可以通过配置编译选项打开) ,这里展示如何使用新接口用ECC 进行加密解密。 新接口是真的方便,基本上你都不需要懂啥密码学知识,对我们这种密码白痴来说太好了 头文件 生成密钥对 导出公

    2024年02月05日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包