wordpress 企业站模版,sspai 少数派wordpress,近期国际军事新闻,分销平台有哪些?一、需求背景
控台项目甲方进行安全测试#xff0c;测试报告其中一条#xff1a;敏感信息明文传输 1 敏感信息明文传输 中危 查询接口传输手机号、银行卡号等敏感信息时未加密/脱敏处理。
二、解决方案
讨论出的方案是通过前端查询条件加密#xff0c;后端对加密的…一、需求背景
控台项目甲方进行安全测试测试报告其中一条敏感信息明文传输 1 敏感信息明文传输 中危 查询接口传输手机号、银行卡号等敏感信息时未加密/脱敏处理。
二、解决方案
讨论出的方案是通过前端查询条件加密后端对加密的数据解密的方式加解密使用SM2国密方案。具体方案
1.每次登录进控台时生成SM2公私钥对其中私钥放进登录的session user信息中公钥返回给前端
2.前端拿到公钥放入cookie前端查询条件使用cookie SM2公钥加密放入临时字段传输时将临时字段数据赋值给需要加密的字段将加密后的数据发送post如果是对整个查询条件加密则更简单
原传输参数regCapital112acct6222081202000000206
原传输参数regCapital112acct564a761bc0d8c260d84abf25fa516eb09f04cb49bfb557943060c0879a4159736a70f4b2463fc65941bd1f29731f35570467e98ec916d091ad651de7afeb1ac8ff1ac05a9bc6df12bbd447fa1dec75a517c611a8557fe7a8e378055cff3f3d4f299b69e621ebd1260cfd331167d45f03
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 MapString, String genSm2KeyPair() {try {MapString, 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, 04cipherDataHex);}
}2.login.java执行公私钥对
SessionUser suer new SessionUser(userInfo, custInfo, roleIdArray, roleName, roleRank);MapString, 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 typetext/javascript src${rc.contextPath}/js/sm-crypto/sm2.js${refreshDate}/script......td scoperowinput namecertNo classform-control styleheight:30px;width:300px;//tdtd styledisplay:noneinput namecertNoSm2 classform-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 formDatadocument.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-。。