sm4加密/解密-postman

news/2026/1/20 23:39:00/文章来源:https://www.cnblogs.com/smallfa/p/19509075

sm4加密/解密-postman

1、SmEncryptUtil  sm4加密

 

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.symmetric.SymmetricCrypto;

/**
* sm4加密
*/
public class SmEncryptUtil {
private final static String appSecret= "7f774ece1231231313123131";

/*
发送方加密签名
1、发送方准备原始数据
2、发送方使用SM4算法加密数据,加密数据=SM4(appSecret,原始数据)
3、发送方生成时间戳、随机数
4、发送方将加密包、appId、appSecret、时间戳、随机数按照先后顺序依次拼接形成待签名串
5、发送方使用SM3算法计算待签名串的哈希值作为签名值

传参:原始数据
返回:加密数据、签名值等信息
*/

/**
* 加密数据
* @param rawData 原始数据
* @return 加密后的数据
*/
public static String encryptData(String rawData) {
// 修正:appAKA 改为 appSecret
return encryptData(rawData, appSecret);
}

/**
* 加密数据
* @param rawData 原始数据
* @param appSecret 密钥
* @return 加密后的数据
*/
public static String encryptData(String rawData, String appSecret) {
try {
// 使用appSecret生成16位密钥
SymmetricCrypto sm4 = SmUtil.sm4(DigestUtil.md5Hex16(appSecret).getBytes());
// 加密数据
return sm4.encryptHex(rawData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* 生成签名
* @param encryptedData 加密数据
* @param appId 应用ID
* @param timeStamp 时间戳
* @param nonce 随机数
* @return 签名值
*/
public static String generateSignature(String encryptedData, String appId, String timeStamp, String nonce) {
// 修正:appAKA 改为 appSecret
return generateSignature(encryptedData, appId, timeStamp, nonce, appSecret);
}

/**
* 生成签名
* @param encryptedData 加密数据
* @param appId 应用ID
* @param timeStamp 时间戳
* @param nonce 随机数
* @param appSecret 密钥
* @return 签名值
*/
public static String generateSignature(String encryptedData, String appId, String timeStamp, String nonce, String appSecret) {
try {
// 拼接待签名串
String signCap = encryptedData + appId + appSecret + timeStamp + nonce;
// 使用SM3算法计算哈希值
Digester digester = DigestUtil.digester("sm3");
return digester.digestHex(signCap);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* 完整的加密和签名生成
* @param rawData 原始数据
* @param appId 应用ID
* @param timeStamp 时间戳
* @param nonce 随机数
* @return 加密和签名信息
*/
public static EncryptResult encryptAndSign(String rawData, String appId, String timeStamp, String nonce) {
// 修正:appAKA 改为 appSecret
return encryptAndSign(rawData, appId, timeStamp, nonce, appSecret);
}

/**
* 完整的加密和签名生成
* @param rawData 原始数据
* @param appId 应用ID
* @param timeStamp 时间戳
* @param nonce 随机数
* @param appSecret 密钥
* @return 加密和签名信息
*/
public static EncryptResult encryptAndSign(String rawData, String appId, String timeStamp, String nonce, String appSecret) {
EncryptResult result = new EncryptResult();
try {
// 加密数据
String encryptedData = encryptData(rawData, appSecret);
result.setEncryptedData(encryptedData);

// 生成签名
String signature = generateSignature(encryptedData, appId, timeStamp, nonce, appSecret);
result.setSignature(signature);

result.setAppId(appId);
result.setTimeStamp(timeStamp);
result.setNonce(nonce);
result.setSuccess(true);
} catch (Exception e) {
e.printStackTrace();
result.setSuccess(false);
result.setErrorMsg(e.getMessage());
}
return result;
}

/**
* 加密结果封装类
*/
public static class EncryptResult {
private boolean success;
private String encryptedData;
private String signature;
private String appId;
private String timeStamp;
private String nonce;
private String errorMsg;

// getter和setter方法
public boolean isSuccess() {
return success;
}

public void setSuccess(boolean success) {
this.success = success;
}

public String getEncryptedData() {
return encryptedData;
}

public void setEncryptedData(String encryptedData) {
this.encryptedData = encryptedData;
}

public String getSignature() {
return signature;
}

public void setSignature(String signature) {
this.signature = signature;
}

public String getAppId() {
return appId;
}

public void setAppId(String appId) {
this.appId = appId;
}

public String getTimeStamp() {
return timeStamp;
}

public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}

public String getNonce() {
return nonce;
}

public void setNonce(String nonce) {
this.nonce = nonce;
}

public String getErrorMsg() {
return errorMsg;
}

public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}

@Override
public String toString() {
return "EncryptResult{" +
"success=" + success +
", encryptedData='" + encryptedData + '\'' +
", signature='" + signature + '\'' +
", appId='" + appId + '\'' +
", timeStamp='" + timeStamp + '\'' +
", nonce='" + nonce + '\'' +
", errorMsg='" + errorMsg + '\'' +
'}';
}
}
}

 

 

 

 

 

 

 

 

2、SmDecryptUtil  SM4解密 + SM3验签 工具类

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONUtil;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
* SM4解密 + SM3验签 工具类
* 依赖:Hutool 5.8.0+(需引入hutool-crypto、hutool-json、hutool-core模块)
*/
public class SmDecryptUtil {
// 统一修改为指定的appSecret密钥
private final static String appSecret = "7f774ece1231231313123131";
// 时间戳格式常量
private final static String TIME_STAMP_FORMAT = "yyyyMMddHHmmss";
// 时间戳有效时长(分钟)
private final static int TIME_STAMP_VALID_MINUTES = 20;

/*
接收方验签解密流程:
1、接收方从请求中获取appId、nonce、timeStamp、加密包、signature;
2、拼接待签名串:加密包 + appId + appSecret + timeStamp + nonce,通过SM3验签;
3、验签通过后,使用SM4解密加密包得到原始数据。
*/

/**
* 核心解密验签方法
* @param appSecret 密钥
* @param appId 应用ID
* @param timeStamp 时间戳(yyyyMMddHHmmss)
* @param nonce 随机数
* @param signature 签名值
* @param bodyStr 加密数据
* @return 解密后的原始字符串(验签/参数异常返回对应错误信息)
*/
public static String decryptJson(String appSecret, String appId, String timeStamp, String nonce, String signature, String bodyStr) {
// 1. 参数非空校验
if (StrUtil.isAnyBlank(appSecret, appId, timeStamp, nonce, signature, bodyStr)) {
return "参数异常:核心参数不能为空";
}

try {
// 2. 时间戳有效性校验
LocalDateTime timeStampTime = DateUtil.parseLocalDateTime(timeStamp, TIME_STAMP_FORMAT);
LocalDateTime now = LocalDateTime.now();
LocalDateTime minTime = now.minusMinutes(TIME_STAMP_VALID_MINUTES);
LocalDateTime maxTime = now.plusMinutes(TIME_STAMP_VALID_MINUTES);

if (timeStampTime.isBefore(minTime) || timeStampTime.isAfter(maxTime)) {
return "时间戳异常:超出" + TIME_STAMP_VALID_MINUTES + "分钟有效范围";
}

// 3. SM3验签
Digester digester = DigestUtil.digester("sm3");
String signSource = bodyStr + appId + appSecret + timeStamp + nonce;
String localSignature = digester.digestHex(signSource);

if (!localSignature.equals(signature)) {
return "签名异常:本地计算签名[" + localSignature + "]与传入签名[" + signature + "]不一致";
}

// 4. SM4解密
SymmetricCrypto sm4 = SmUtil.sm4(DigestUtil.md5Hex16(appSecret).getBytes());
String decryptStr = sm4.decryptStr(bodyStr);

if (StrUtil.isBlank(decryptStr)) {
return "解密异常:解密结果为空";
}
return decryptStr;

} catch (Exception e) {
// 捕获具体异常信息,便于排查
return "异常:" + e.getClass().getSimpleName() + " - " + e.getMessage();
}
}

/**
* 从HttpServletRequest中获取参数并解密
* @param request 请求对象
* @param bodyStr 加密的请求体
* @return 解密后的字符串
*/
public static String getDecryptJson(HttpServletRequest request, String bodyStr) {
// 从请求头获取参数
String appId = request.getHeader("appId");
String timeStamp = request.getHeader("timestamp");
String nonce = request.getHeader("nonce");
String signature = request.getHeader("signature");

// 调用核心解密方法(使用修改后的默认appSecret)
return decryptJson(appSecret, appId, timeStamp, nonce, signature, bodyStr);
}

/**
* 解密并转换为指定类型的对象(从Request获取参数)
* @param request 请求对象
* @param bodyStr 加密的请求体
* @param typeReference 目标类型引用
* @param <T> 泛型类型
* @return 转换后的对象(异常/非JSON返回null)
*/
public static <T> T getDecryptObject(HttpServletRequest request, String bodyStr, TypeReference<T> typeReference) {
String appId = request.getHeader("appId");
String timeStamp = request.getHeader("timestamp");
String nonce = request.getHeader("nonce");
String signature = request.getHeader("signature");

// 打印调试信息
System.out.println("bodyStr为:" + bodyStr);
System.out.println("appId为:" + appId);
System.out.println("nonce为:" + nonce);
System.out.println("timestamp为:" + timeStamp);
System.out.println("signature为:" + signature);

// 先解密(使用修改后的默认appSecret)
String decryptJson = decryptJson(appSecret, appId, timeStamp, nonce, signature, bodyStr);
System.out.println("bodyStr解析结果为" + decryptJson);

// 校验是否为JSON格式,再转换
if (StrUtil.isNotBlank(decryptJson) && JSONUtil.isTypeJSON(decryptJson)) {
return JSONUtil.toBean(decryptJson, typeReference, true);
}
return null;
}

/**
* 解密并转换为指定类型的对象(手动传入参数)
* @param appId 应用ID
* @param timeStamp 时间戳
* @param nonce 随机数
* @param signature 签名值
* @param bodyStr 加密数据
* @param typeReference 目标类型引用
* @param <T> 泛型类型
* @return 转换后的对象(异常/非JSON返回null)
*/
public static <T> T getDecryptObject(String appId, String timeStamp, String nonce, String signature, String bodyStr, TypeReference<T> typeReference) {
// 先解密(使用修改后的默认appSecret)
String decryptJson = decryptJson(appSecret, appId, timeStamp, nonce, signature, bodyStr);

// 校验是否为JSON格式,再转换
if (StrUtil.isNotBlank(decryptJson) && JSONUtil.isTypeJSON(decryptJson)) {
return JSONUtil.toBean(decryptJson, typeReference, true);
}
return null;
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1191202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Paxos共识算法原理及其在分布式系统高可用性保障中的应用剖析

【精选优质专栏推荐】 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解《网安渗透工具使用教程(全)》 —— 一站式工具手册《CTF 新手入门实战教…

054.Dijkstra模板+反向索引堆优化 + 经典题目

DijkstraBFS + 贪心(priority_queue)加权有向图不能处理负权Dij(普通堆) O ( M * logM )M : 边数const int N=1e5+5; const int INF=0x3f3f3f3f;vector<pair<int,int>>gra[N]; bool vis[N]; int dis[N];…

Hello AgentScope Java

作者&#xff1a;远云 随着 LLM 应用的飞速发展&#xff0c;越来越多的 Agent 应用开始走近每个人。围绕着 Agent 应用的核心&#xff0c;目前业界有零代码、低代码和高代码三条主流的技术路线。AgentScope 作为 Python 社区中受到广泛应用的高代码框架&#xff0c;在 Java 生态…

(模型量化学习)基础准备

1.FLOPS&#xff08;大写&#xff09;和TOPSFLOPS指的是一秒钟可以处理的浮动小数点运算次数,而TOPS是一秒钟可以处理了的整形运算次数的能力&#xff0c;衡量计算机硬件性能&#xff0c;计算能力的一个单位。注意FLOPS与FLOPs不同&#xff0c;FLOPs是衡量模型大小的一个指标。…

Nature重磅!打破AI安全边界:微调代码为何会引发全面失准?

研究团队在OpenAI和阿里巴巴云模型上的实验揭示了一个令人不安的现象&#xff1a;如果你教一个大语言模型去写包含安全漏洞的代码&#xff0c;它学到的绝不仅仅是写代码。一项刚刚发表在《自然》杂志上的重磅新研究&#xff0c;发现了大模型安全的新幽灵&#xff1a;微小的恶意…

智谱新模型也用DeepSeek的MLA,苹果M5就能跑

这是一个30B总参数、仅3B激活参数的混合专家&#xff08;MoE&#xff09;架构模型&#xff0c;官方给它的定位是“本地编程与智能体助手”。 智谱AI上市后&#xff0c;再发新成果。 开源轻量级大语言模型GLM-4.7-Flash&#xff0c;直接替代前代GLM-4.5-Flash&#xff0c;API免…

【Da】达芬奇基础设置

--本篇导航--工程项目基础设置偏好设置代理优化面板写在前面:达芬奇用的是官方的免费版Davinvi Resolve 20,很多Studio版的功能就没涉及到了。 基本剪辑、调色的部分,此笔记中都涉及到了。 学达芬奇仅仅是想做长视频…

XML外部实体注入(XXE)漏洞深度剖析与防御实践

【精选优质专栏推荐】 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解《网安渗透工具使用教程(全)》 —— 一站式工具手册《CTF 新手入门实战教…

快讯|萝博派对(RoboParty)Roboto_Origin项目全栈上线:1.2m人形机器人硬件结构、BOM清单、3m/s运动控制算法完全开源;灵心巧手与Xbotics推出线上实习项目,打造人才生态

&#x1f43e; 具身智能 / AI 赛道&#xff0c;过去24小时的行业焦点&#xff0c;像北京的冬日阳光一样&#xff0c;一半洒在突破想象力的AI疆界&#xff0c;另一半则直射向机器人领域那些试图“掀翻桌子”的年轻身影。当GPT-5.2 Pro在数学的圣殿里留下足迹时&#xff0c;一群0…

阿里云ECS部署hadoop+MapReduce+Spark实践

阿里云ECS部署hadoop+MapReduce+Spark实践host说明 Namenode:主机结点 Datanode1:数据节点1 Datanode2:数据节点2 私网ip(在阿里云查看) 172.xx.xxx.xx Namenode 172.xx.xx.xx Datanode1 172.xx.xxx.xxx D…

GBase 8s MTK工具,让数据库迁移更简单

在企业数字化转型和国产化替代的浪潮中&#xff0c;数据迁移往往是让IT团队最头疼的环节之一&#xff1a;源端系统五花八门&#xff0c;迁移过程怕丢数据、怕出错&#xff0c;操作复杂门槛高……而与GBase 8s数据库配套的GBase Migration Toolkit&#xff08;简称 MTK&#xff…

谷歌新发现:DeepSeek推理分裂出多重人格,左右脑互搏越来越聪明

谷歌最新研究表明&#xff0c;DeepSeek-R1这类顶尖推理模型在解题时&#xff0c;内部会自发“分裂”出不同性格的虚拟人格&#xff0c;比如外向的、严谨的、多疑的……AI变聪明的真相居然是正在“脑内群聊”&#xff1f;&#xff01;谷歌最新研究表明&#xff0c;DeepSeek-R1这…

【课程设计/毕业设计】机器学习基于python-cnn深度学习识别水果是否成熟

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

GBase 8c数据库故障定位解析

南大通用GBase 8c数据库定位数据库故障&#xff0c;可从以下方面进行排查分析&#xff1a;日志&#xff1a;数据库日志记录了数据库服务端启动、运行或停止时出现的问题&#xff0c;当数据库在启动、运行或停止的过程中出现问题时&#xff0c;数据库用户可以通过运行日志快速分…

无需PLC控制,威纶通触摸屏直接实现与台达变频器通信控制

一、PLC通信简介 威纶通(Weinview)触摸屏作为工业人机交互核心,与台达(Delta)变频器的通信是自动化控制系统中常见的应用场景。通过两者的稳定通信,可实现变频器运行状态监控、参数设置、启停控制等功能,简化操…

巴菲特的市场周期理解

巴菲特的市场周期理解 关键词:巴菲特、市场周期、价值投资、市场波动、长期投资、风险评估、投资策略 摘要:本文深入探讨了巴菲特对市场周期的理解。从背景介绍入手,阐述研究目的、预期读者、文档结构及相关术语。接着剖析核心概念,揭示市场周期与巴菲特投资理念的联系,并…

探索健康管理虚拟仿真实训室的创新教学应用

一、推动教学理念从知识传授向能力建构转型 健康管理虚拟仿真实训室的应用&#xff0c;首先带来的是教学理念的深刻革新。传统教学往往偏重于理论知识与标准流程的讲授&#xff0c;学生缺乏在复杂、动态的真实情境中综合决策与应急处置的机会。点击获取方案 而健康管理虚拟仿真…

GBase 8c数据库操作系统故障定位介绍

南大通用GBase 8c数据库查询状态时&#xff0c;显示一个节点上所有实例都不正常时&#xff0c;可能是操作系统发生了故障。可以通过如下方法确定操作系统是否存在问题&#xff1a;1、通过 SSH 或者其它远程登录工具登录该节点。如果连接失败&#xff0c;请尝试通过 ping 发包检…

【Effective Modern C++】第二章 auto:6. 当auto推导的类型不符合要求时,使用显式类型初始化习惯用法

个人认为原著写的非常难懂&#xff0c;所以精简总结如下&#xff1a; auto与代理类的问题&#xff1a; 当使用auto进行类型推导时&#xff0c;如果表达式返回的是代理类&#xff0c;auto会推导出代理类型而不是被代理的实际类型&#xff0c;可能导致未定义行为。 例如&#…