SM2签名算法

白茶清欢
package org.chemical;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 *
 */
@Slf4j
public class Sm2Demo {


    private static String publicKey;
    private static String privateKey;

    static {
                /* 依赖
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.0</version>
        </dependency>
         */

        // ***********************第一部分:生成密钥******************************
        //1.生成新的公私钥
        SM2 sm2 = SmUtil.sm2().initKeys();
        //2. 获取公钥
        publicKey = sm2.getPublicKeyBase64();
        log.info("生成了公私钥,公钥为:{}", publicKey);
        //3. 获取私钥
        privateKey = sm2.getPrivateKeyBase64();
        log.info("生成了公私钥,私钥为:{}", privateKey);
    }

    public static void main(String[] args) throws IOException {


        // ***********************第二部分:请求发起方-处理请求数据 ******************************
        // 1. 构造业务数据
        Map<String, Object> body = new HashMap<>();
        body.put("key1", System.nanoTime());
        body.put("key2", "value2");
        body.put("key3", Arrays.asList("1.1","1.2"));

        // 2. 转成JSON字符串
        String bodyJson = JSON.toJSONString(body);
        log.info("请求体的json数据: {}", bodyJson);

        // 3. 转成base64字符串

        String bodyValue = Base64.encode(bodyJson);
        log.info("请求体: {}", toLog(bodyValue));


        // ***********************第三部分:请求发起方-生成签名 ******************************

        // 获取当前时间戳(毫秒) 接收方会校验该值, 收到数据时不可超过1分钟
        long currentMillis = System.currentTimeMillis();
        // 获取随机数
        Random random = new SecureRandom();
        int nonce = random.nextInt(1000000);
        // 拼接需要生成签名的数据
        String value1 = String.format("%s%s%s", bodyValue, currentMillis, nonce);
        // 获取数据摘要
        byte[] content1 = value1.getBytes(StandardCharsets.UTF_8);
        // 获取签名
        SM2 privateSm2 = SmUtil.sm2(privateKey, null);
        String signature = Base64.encode(privateSm2.sign(content1));

        /*
            将时间戳、随机数、签名值,放到请求头中
            request.setHeader("X-millis", currentMillis + "");
            request.setHeader("X-nonce", nonce + "");
            request.setHeader("X-signature", signature);
            request.setHeader("X-digest", digest);
         */

        log.info("签名结果: {}, value1={}", signature, toLog(value1));

        // ***********************第四部分:请求接收方-验证签名 ******************************

        // 1. 从请求头获取 时间戳、随机数、签名值,从请求体获取base64的数据
        String millisFromRequestHeader = currentMillis+"";
        String nonceFromRequestHeader = nonce+"";
        String signatureFromRequestHeader = signature;
        String valueFromRequestBody = bodyValue;

        // 2. 拼接数据
        String value2 = String.format("%s%s%s", bodyValue, millisFromRequestHeader, nonceFromRequestHeader);
        byte[] content2 = value2.getBytes(StandardCharsets.UTF_8);

        // 3. 验证签名
        byte[] signatureBytes = Base64.decode(signatureFromRequestHeader);
        SM2 publicSm2 = SmUtil.sm2(null, publicKey);

        long startTime = System.currentTimeMillis();
        boolean verify = publicSm2.verify(content2, signatureBytes);
        long endTime = System.currentTimeMillis();

        String jsonParam = Base64.decodeStr(valueFromRequestBody);
        log.info("签名验证结果: {}, 耗时: {}ms, 请求体的json数据: {}", verify, (endTime - startTime), toLog(jsonParam));

        if(verify){
            // 验签通过,继续业务处理
            // do something ...
        }else {
            // 验签失败, 返回失败信息
            // do something ...
        }


    }

    static String toLog(String bodyValue){
       return bodyValue.length() > 100 ? bodyValue.substring(0, 100) : bodyValue;
    }

}


文章版权声明:除非注明,否则均为白茶清欢的个人技术分享原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
AddoilApplauseBadlaughBombCoffeeFabulousFacepalmFecesFrownHeyhaInsidiousKeepFightingNoProbPigHeadShockedSinistersmileSlapSocialSweatTolaughWatermelonWittyWowYeahYellowdog
评论列表 (暂无评论,682人围观)

还没有评论,来说两句吧...