一、需求背景

控台项目甲方进行安全测试,测试报告其中一条:敏感信息明文传输

1

敏感信息明文传输

中危

查询接口传输手机号、银行卡号等敏感信息时未加密/脱敏处理。

二、解决方案

讨论出的方案是通过前端查询条件加密,后端对加密的数据解密的方式,加解密使用SM2国密方案。具体方案:

1.每次登录进控台时生成SM2公私钥对,其中私钥放进登录的session user信息中,公钥返回给前端;

2.前端拿到公钥放入cookie,前端查询条件使用cookie SM2公钥加密放入临时字段,传输时将临时字段数据赋值给需要加密的字段,将加密后的数据发送post;(如果是对整个查询条件加密则更简单);

原传输参数:&regCapital=112&acct=6222081202000000206

原传输参数:&regCapital=112&acct=564a761bc0d8c260d84abf25fa516eb09f04cb49bfb557943060c0879a4159736a70f4b2463fc65941bd1f29731f35570467e98ec916d091ad651de7afeb1ac8ff1ac05a9bc6df12bbd447fa1dec75a517c611a8557fe7a8e378055cff3f3d4f299b69e621ebd1260cfd331167d45f03

3.后端接收到加密后的数据,使用session中私钥进行解密。

三、代码实现

1.Sm2Utils.java文件,包含生成公私钥对,后端对前端加密数据解密的方法。

package com.xxx.xxx.util;import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;/*** @ClassName Sm2Utils* @Description 生成SM2公私钥对* @Author whb* @Date 2024/10/9 15:53* @Version 1.0**/
public class Sm2Utils {private static final X9ECParameters SM2_EC_PARAMS = GMNamedCurves.getByName("sm2p256v1");private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(SM2_EC_PARAMS.getCurve(),SM2_EC_PARAMS.getG(),SM2_EC_PARAMS.getN(),SM2_EC_PARAMS.getH());/*** 生成SM2密钥对* @return String[0]=公钥(04开头未压缩格式), String[1]=私钥(64字符16进制)*/public static String[] generateKeyPair() {try {// 1. 初始化密钥生成器ECKeyPairGenerator generator = new ECKeyPairGenerator();ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(DOMAIN_PARAMS, new SecureRandom());generator.init(keyGenParams);// 2. 生成密钥对AsymmetricCipherKeyPair keyPair = generator.generateKeyPair();// 3. 获取私钥(去掉前面的00)ECPrivateKeyParameters privateKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate();String privateKey = leftPad(privateKeyParams.getD().toString(16), 64, '0');// 4. 获取公钥(04开头未压缩格式)ECPublicKeyParameters publicKeyParams = (ECPublicKeyParameters) keyPair.getPublic();ECPoint publicKeyPoint = publicKeyParams.getQ();String publicKey = "04" +leftPad(publicKeyPoint.getAffineXCoord().toBigInteger().toString(16), 64, '0') +leftPad(publicKeyPoint.getAffineYCoord().toBigInteger().toString(16), 64, '0');return new String[]{publicKey, privateKey};} catch (Exception e) {throw new RuntimeException("生成SM2密钥对失败", e);}}private static String leftPad(String input, int size, char padChar) {if (input.length() >= size) {return input;}StringBuilder sb = new StringBuilder(size);for (int i = input.length(); i < size; i++) {sb.append(padChar);}sb.append(input);return sb.toString();}/*** SM2解密* @param privateKeyHex 16进制私钥(64字符)* @param cipherDataHex 加密数据(16进制字符串)* @return 解密后的原文*/public static String decrypt(String privateKeyHex, String cipherDataHex) {try {// 1. 验证私钥格式if (privateKeyHex == null || privateKeyHex.length() != 64) {throw new IllegalArgumentException("私钥必须是64字符的16进制字符串");}// 2. 验证加密数据格式if (cipherDataHex == null || cipherDataHex.length() < 194) {throw new IllegalArgumentException("加密数据格式不正确,长度不足");}// 3. 准备私钥参数BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);ECPrivateKeyParameters privateKeyParams = new ECPrivateKeyParameters(privateKeyD, DOMAIN_PARAMS);// 4. 初始化SM2解密引擎(使用C1C3C2模式与前端一致)SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);engine.init(false, privateKeyParams);// 5. 解码加密数据byte[] cipherData = Hex.decode(cipherDataHex);// 6. 验证数据头if (cipherData[0] != 0x04) {throw new IllegalArgumentException("加密数据必须以04开头");}// 7. 解密数据byte[] decrypted = engine.processBlock(cipherData, 0, cipherData.length);return new String(decrypted, "UTF-8");} catch (Exception e) {throw new RuntimeException("SM2解密失败: " + e.getMessage(), e);}}/*** 生成SM2密钥对* @return 包含私钥(64字符)和公钥(130字符04开头)的数组*/public static Map<String, String> genSm2KeyPair() {try {Map<String, String> keyMap = new HashMap<>(2);String[] keys =  generateKeyPair();keyMap.put("sm2PriKey", keys[1]);keyMap.put("sm2PubKey", keys[0]);return keyMap;} catch (Exception e) {throw new RuntimeException("生成SM2密钥对失败", e);}}/*** SM2解密* @param cipherDataHex 前端加密后的16进制字符串* @param privateKeyHex 16进制格式的私钥(64字符)* @return 解密后的原始字符串*/public static String queryDataSm2Decrypt(String cipherDataHex, String privateKeyHex) {return decrypt(privateKeyHex, "04"+cipherDataHex);}
}

2.login.java执行公私钥对

SessionUser suer = new SessionUser(userInfo, custInfo, roleIdArray, roleName, roleRank);Map<String, String> sm2KeyMaps = Sm2Utils.genSm2KeyPair();suer.setSm2PriKey(sm2KeyMaps.get("sm2PriKey"));
SessionUser.pushUser(suer, request);.........//页面使用SM2公钥加签sm2PubKey
mav.addObject("sm2PubKey", sm2KeyMaps.get("sm2PubKey"));

3.前端页面对数据加密

登录后js对公钥存放到cookie中

jQuery.cookie("login_sm2pubkey","${sm2PubKey}");

页面使用,先引用sm2.js,下载sm-crypto/dist at master · JuneAndGreen/sm-crypto · GitHub

<script type="text/javascript" src="${rc.contextPath}/js/sm-crypto/sm2.js${refreshDate}"></script>......<td scope="row"><input name="certNo" class="form-control" style="height:30px;width:300px;"/></td><td style="display:none"><input name="certNoSm2" class="form-control"/></td>......
//先对数据加密
encryptData("userInfoQueryForm");
//post发送
post......function encryptWithSM2(param,sm2PubKey) {// 执行SM2加密const cipherMode = 1; // 1 - C1C3C2 模式const encryptData = sm2.doEncrypt(param, sm2PubKey, cipherMode);return encryptData;}function encryptData(formid) {var sm2PubKey = jQuery.cookie("login_sm2pubkey");var formData=document.getElementById(formid);if (!formData.certNo.value == "") {formData.certNoSm2.value = encryptWithSM2(formData.certNo.value,sm2PubKey)}}

4.后端解密

String sm2HexD = SessionUser.getUser(request).getSm2PriKey();String certNo = queryForm.getCertNo();if (com.changingpay.commons.util.StringUtils.isNotEmpty(sm2HexD)) {certNo = Sm2Utils.queryDataSm2Decrypt(queryForm.getCertNo(),sm2HexD);}

四、SM2解密坑

1.前端使用cipherMode = 1; // 1 - C1C3C2 模式,后端解密也需要用C1C3C2 模式,不然报错

2.后端解密时,需要对前端加密的数据前面加04,不然解密报错Invalid point encoding 0x-。。

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

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

相关文章

【Python】Flask网页

Flask第三方库安装命令&#xff1a;pip install flask代码&#xff1a;from flask import Flask app Flask(__name__)app.route("/") def hello():return "Hello world!"if __name__ "__main__":app.run()其中的"Hello world!"可以改…

数字资产革命中的信任之锚:RWA法律架构的隐形密码

首席数据官高鹏团队律师创作&#xff0c;AI辅助 在数字经济的浪潮中&#xff0c;资产的边界正在被重新定义。当一块地产、一笔应收账款、甚至一份碳配额被转化为链上的数字代币时&#xff0c;技术的光芒固然耀眼&#xff0c;但真正决定其生命力的&#xff0c;是背后隐匿的“信…

mobaxterm终端sqlplus乱码问题解决

背景。使用mobaxterm终端连接linux。在查询数据库表注释时发现**&#xff1f;**中文乱码。影响对表的分析。完成以下三个编码设置再打开sqlplus查询含中文的数据就正常了 总结。需要查看sqlplus的编码是什么 SELECT parameter, value FROM nls_database_parameters WHERE pa…

一个简单的分布式追踪系统

1. 准备工作 导入必要的库 import contextvars import time from typing import Any, Optional, Dict, List, Union from dataclasses import dataclass, field2. 定义上下文变量 # 定义两个上下文变量&#xff0c;存储当前 Span 和 Trace _current_span: contextvars.Conte…

【Qt】事件处理、事件分发器、事件过滤器

事件处理 一. 事件事件处理鼠标事件处理按键事件处理定时器事件处理窗口事件处理 二. 事件分发器三. 事件过滤器 虽然 Qt 是跨平台的 C 开发框架&#xff0c;Qt 的很多能力其实是操作系统提供的&#xff0c;只不过 Qt 封装了系统 API&#xff0c;程序是运行在操作系统上的&…

广东省省考备考(第三十八天7.4)——言语理解:逻辑填空(题目训练)

错题解析 本题可从第二空入手&#xff0c;横线处搭配“理论”&#xff0c;且根据“使得”可知&#xff0c;横线处与前文构成因果关系&#xff0c;即“遗传学的空白和古生物证据的缺乏”导致他的理论在某些方面存在不足&#xff0c;A项“捉襟见肘”指拉一拉衣襟&#xff0c;就露…

5G网络切片技术

5G中的网络切片技术是一种通过虚拟化将单一物理网络划分为多个独立、可定制的虚拟网络的技术&#xff0c;旨在满足不同应用场景对网络性能、带宽、时延等需求的差异化要求。以下从技术原理、核心价值、应用场景、实现方式及未来趋势五个维度展开分析&#xff1a;一、技术原理&a…

算法学习笔记:7.Dijkstra 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学领域&#xff0c;图论算法一直占据着重要地位&#xff0c;其中 Dijkstra 算法作为求解单源最短路径问题的经典算法&#xff0c;被广泛应用于路径规划、网络路由等多个场景。无论是算法竞赛、实际项目开发&#xff0c;还是计算机考研 408 的备考&#xff0c;Dijkstr…

汇编 函数调用栈

前言 网上很多对函数栈的解释&#xff0c;说的不是很清楚感觉&#xff0c;尤其是对到底是谁的栈&#xff0c;以及指令的微小但是很致命的细节没说&#xff0c;特写本文&#xff0c;一是帮助自己记忆&#xff0c;二是为了帮助大家&#xff0c;如有疏忽错误请指正。 核心概念 首先…

基于Apache MINA SSHD配置及应用

Apache MINA SSHD 是一个基于 Java 的 SSH 服务器和客户端实现&#xff0c;它是 Apache MINA 项目的一部分&#xff0c;提供了完整的 SSH 协议支持。 主要特性 SSH 协议支持&#xff1a; 支持 SSH2 协议 兼容大多数 SSH 客户端 支持多种加密算法和密钥交换方法 服务器功能…

Excel 如何让数据自动按要求排序或筛选?

让数据按要求排序和筛选是Excel数据处理的基础核心功能&#xff0c;也是进行有效分析前必做的准备工作。下面我们分开讲解这两个功能。 一、排序 (Sort)&#xff1a;让数据井井有条 排序的目的是重新排列数据行的顺序&#xff0c;以便更好地观察和比较。 1. 快速单列排序 (最…

Django 安装使用教程

一、Django 简介 Django 是一个高级 Python Web 框架&#xff0c;鼓励快速开发和简洁实用的设计。它内置 ORM、认证系统、后台管理、表单处理、路由控制等功能&#xff0c;广泛用于开发企业级网站、内容管理系统、电商平台等。 二、环境准备 2.1 安装 Python Django 基于 Py…

前沿交叉:Fluent与深度学习驱动的流体力学计算体系

基础模块 流体力学方程求解 1、不可压缩N-S方程数值解法&#xff08;有限差分/有限元/伪谱法&#xff09; Fluent工业级应用&#xff1a;稳态/瞬态流、两相流仿真&#xff08;圆柱绕流、入水问题&#xff09; Tecplot流场可视化与数据导出 2、CFD数据的AI预处理 基于P…

五、Flutter动画

目录1. Flutter 中动画的基本概念是什么&#xff1f;2. 解释 AnimationController 和 Tween 的作用3. 如何实现一个补间&#xff08;Tween&#xff09;动画&#xff1f;4. 什么是隐式动画&#xff1f;举例说明5. 如何实现自定义复杂动画&#xff1f;1. Flutter 中动画的基本概念…

全网唯一/Qt结合ffmpeg实现手机端采集摄像头推流到rtsp或rtmp/可切换前置后置摄像头/指定分辨率帧率

一、前言说明 之前已经实现了Qt结合ffmpeg在安卓上运行&#xff0c;所有在win上的功能&#xff0c;在安卓上都已经实现&#xff0c;比如编码保存到MP4文件&#xff0c;正常解码音视频文件播放等&#xff0c;唯独还差一个功能&#xff0c;尽管用的不多&#xff0c;但是还是有一…

Install Ubuntu 24.04 System

1.制作安装镜像盘&#xff08;U盘&#xff09; 下载rufus制作工具(网址&#xff1a;https://www.xiaomoxz.com/nexus/bi1/rufus4.shtml?bd_vid8643969197265870719&#xff09; 2. 设置U盘启动&#xff1a; F2进入BIOS 3. Install Ubuntu 24.04 Ubuntu下载地址&#xff1a;…

solidjs 处理复杂类型的响应式

solidjs 处理复杂类型的响应式 在 solidjs 里响应式一般直接用 createSignal 就可以&#xff0c;但 createSignal 一般用于基础数据类型。 虽然复杂类型也是可以使用&#xff0c;但基于起细粒度响应性的特性。 一般复杂的数据使用 createSignal 就不是那么友好了。 所以 cre…

爬虫技术-获取浏览器身份认证信息(如 Cookie、Token、Session 等)

方法一&#xff1a;通过浏览器开发者工具查看和提取 Cookie / Token &#x1f4cc; 示例场景&#xff1a; 你在使用一个网站时已经登录了&#xff0c;想看看这个网站是如何保存你的身份凭证的。 &#x1f527; 操作过程&#xff1a; 打开浏览器&#xff08;例如 Chrome&#xf…

[密码学实战]GMT 0136-2024《密码应用HTTP接口规范》解析

[密码学实战]GM/T 0136-2024《密码应用HTTP接口规范》解析国家密码管理局于2025年7月1日正式实施GM/T 0136-2024标准&#xff0c;该规范首次统一了密码服务的HTTP接口设计&#xff0c;为国产密码技术的规模化应用铺平道路。本文结合标准原文&#xff0c;深入剖析其技术细节并给…

Docker 国内镜像列表(免费长期)

Docker 可用镜像源列表&#xff08;7月1日更新-长期维护&#xff09;_dockerhub国内镜像源列表-CSDN博客