记难受的老项目进行安全扫描的坑:敏感数据加密传输和保存

首先我们先创建这么一个JAVA工具类,用里面的main方法来得到SM2加密时需要用到的公钥和私钥,需要注意的是,执行一次就拿到这两个值来放到另一个类中或者数据库中来永久使用,需要调用时从里面调用即可,记得保密!

package com.cn.zj.sm;import java.math.BigInteger;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;public class SMutil
{public static class SM2Key{public String publicKey;    //公钥public String privateKey;   //私钥}private static boolean isEmpty(String str){if(str==null || str.trim().equals("")){return true;}return false;}/*** 生成SM2秘钥*/@SuppressWarnings("deprecation")public static SM2Key generateSM2Key(){SM2 sm2 = SM2.Instance();  AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();  ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();  ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();  BigInteger privateKey = ecpriv.getD();ECPoint publicKey = ecpub.getQ();SM2Key sm2Key = new SM2Key();sm2Key.publicKey = Util.byteToHex(publicKey.getEncoded());sm2Key.privateKey = Util.byteToHex(privateKey.toByteArray());return sm2Key;}/*** SM2加密* @param publickey 公钥* @param src 待加密的明文* @return*/public static String sm2encrypt(String publickey, String str){if(isEmpty(publickey) || isEmpty(str)){return null;}try {return SM2Utils.encrypt(Util.hexToByte(publickey), str.getBytes());} catch (Exception e) {e.printStackTrace();}return null;}/*** SM2解密* @param privatekey   私钥* @param src 待解密的密文* @return*/public static String sm2decrypt(String privatekey, String str){if(isEmpty(privatekey) || isEmpty(str)){return null;}try {return new String(SM2Utils.decrypt(Util.hexToByte(privatekey), Util.hexToByte(str)));} catch (Exception e) {e.printStackTrace();}return null;}/*** SM3加密* @param str    待加密的明文* @return*/public static String sm3encrypt(String str){if(isEmpty(str)){return null;}byte[] md = new byte[32];  byte[] msg1 = str.getBytes();  SM3Digest sm3 = new SM3Digest();  sm3.update(msg1, 0, msg1.length);  sm3.doFinal(md, 0);  return new String(Hex.encode(md));  }/*** sm3密码校验* @param str 待校验的明文* @param sm3Str sm3加密后的密文 * @return*/public static boolean sm3decrypt(String str, String sm3Str){if(isEmpty(str) || isEmpty(sm3Str)){return false;}return sm3Str.equalsIgnoreCase(sm3encrypt(str));       }/*** SM4加密* @param str    待加密的明文* @return*/public static String sm4encrypt(String str){if(isEmpty(str)){return null;}String ret = new SM4Utils().encryptData_ECB(str);  return ret;}/*** SM4加密* @param str 待解密的密文* @return*/public static String sm4decrypt(String str){if(isEmpty(str)){return null;}String ret = new SM4Utils().decryptData_ECB(str);  return ret;}public static void main(String[] args){SM2Key sm2Key = generateSM2Key();System.out.println("私钥privateKey:"+sm2Key.privateKey);System.out.println("公钥publicKey: "+sm2Key.publicKey);}
}

这是一个在上面的工具类基础上写出的另一个更加功能完善的工具类,可以直接调用,公钥和私钥都已经放在上面


package com.cn.zj.sm;import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import com.xquant.xqa.component.util.utils.StringUtil;/*** @program: SMHandler* @description: 国密加密解密* @author: zhangjun* @create: 2021/03/30**/
@Service
public class SMHandler {//SM2私钥private static final String privatekey = "24F2401757F59665DED44ECEC08C7314E14F74E95B0720D0FA03E7992440CF1A";//SM2公钥private static final String pubkeyHex = "04509AEB08F6645C6AC92B965A5EAA6EE7761908A4AE1454DA537A855F1ADF0D611D45486362D856D7DFB45688EC969B96FD32E5E008FFE9E74E4A424A422DF3AC";private Logger logger = LoggerFactory.getLogger(SMHandler.class);/*** @Title: passWordCryptBySM2_3* @Description: 解析前端传入密文,转译成数据库存储密文,*  前端加密逻辑要求:密文 = SM2 (明文)+SM3 (明文)*  存入数据库密文要求:密文 = SM3 (明文)* @param str 前端传入密文* @return: java.lang.String 密码明文* @throws*/public String passWordCryptBySM2_3(String str){//【1】分割传输过来的密文,得到 0.SM2加密过的明文  1.SM3算法加密后的密文String[] strArr = StringUtil.split(str,"|");if(ArrayUtils.isEmpty(strArr) || strArr.length != 2){logger.info("完整性校验失败:"+ str);return null;}//【2】用SM2私钥解密传输过来的密文,获取明文String privateKey = privatekey;String passWord = SMutil.sm2decrypt(privateKey,strArr[0]);String passWd = SMutil.sm2decrypt(privateKey,strArr[1]);//【3】完整性校验——判断明文与加密后的密文是否相同
//        if(!SMutil.sm3decrypt(passWord,strArr[1])){if(!SMutil.sm3decrypt(passWord,passWd)){logger.info("完整性校验失败:"+ str);return null;}
//        System.out.println("传入密文:"+str);
//        System.out.println("SM2密钥加密密文:"+strArr[0]);
//        System.out.println("SM3加密密文:"+strArr[1]);
//        System.out.println("密码:"+passWord);//【4】返回SM3加密后明文
//        return strArr[1];//【4】返回密码明文return passWord;}/*** @Title: passWordCryptBySM2_3_4* @Description: 解析前端传入密文,转译成数据库存储密文,*  前端加密逻辑要求:密文 = SM2 (明文+SM3 (明文))*  存入数据库密文要求:密文 = SM4 (明文)* @param str 前端传入密文* @return: java.lang.String 数据库存储密文* @throws*/public String passWordCryptBySM2_3_4(String str){//【1】用SM2私钥解密传输过来的密文,得到SM3算法加密后的密文及明文String privateKey = privatekey;String mm = SMutil.sm2decrypt(privateKey,str);//根据标识符切割【0】:SM3算法加密后的密文,【1】明文String[] mmArr = StringUtil.split(mm,"|");if(ArrayUtils.isEmpty(mmArr) || mmArr.length != 2){logger.info("传入密文解密失败:"+ str);return null;}String mw_sm3 = mmArr[0];String passWord = mmArr[1];//【2】完整性校验——判断明文与加密后的密文是否相同if(!SMutil.sm3decrypt(passWord,mw_sm3)){logger.info("完整性校验失败:"+ mw_sm3);return null;}//【3】SM4加密明文,存入数据库String mw_sm4 = SMutil.sm4encrypt(passWord);//        System.out.println("传入密文:"+str);//        System.out.println("SM2密钥解密后密文:"+mm);//        System.out.println("SM3加密后密文:"+mw_sm3);//        System.out.println("SM4加密后密文:"+mw_sm4);//        System.out.println("密码:"+passWord);return mw_sm4;}/*** @Title: accountDecryptBySM2* @Description: 解析前端传入密文,转译成明文*  前端加密逻辑要求:密文 = SM2 (明文)* @param str* @return: java.lang.String* @throws*/public String accountDecryptBySM2(String str){String privateKey = privatekey;String mm = SMutil.sm2decrypt(privateKey,str);if(mm == null){logger.info("传入密文解密失败:"+ str);return null;}return mm;}/*** @Title: passWordEnryptBySM3* @Description: 加密密码存入数据库*  加密要求:密文 = SM3(明文)* @param str* @return: java.lang.String* @throws*/public String passWordEnryptBySM3(String str){String mm = SMutil.sm3encrypt(str);if(mm == null){logger.info("加密失败:"+ str);return null;}return mm;}/*** @Title: passWordEnryptBySM2* @Description: 加密密码存入数据库*  加密要求:密文 = SM2(公钥,明文)* @param str* @return* @throws*/public String passWordEnryptBySM2(String str) {String publicKey = ConfigSupport.getProperty("SM2.pubkeyHex", pubkeyHex);String mm = SMutil.sm2encrypt(publicKey, str);if(mm == null){logger.info("加密失败:"+ str);return null;}return mm;}/*** @Title: passWordDecryptBySM2* @Description: 返回解密后的明文*  解密要求:明文 = SM2(私钥, 密文)* @param str* @return* @throws*/public String passWordDecryptBySM2(String str) {String privateKey = privatekey;String passWord = SMutil.sm2decrypt(privateKey, str);if(passWord == null){logger.info("解密失败:"+ str);return null;}return passWord;}public static void main(String[] args) {String publicKey = ConfigSupport.getProperty("SM2.pubkeyHex", pubkeyHex);String mm = SMutil.sm2encrypt(publicKey, "111111");String str2 = "16ebf7bd3f730247ff2df62ddfe30201487c0c0ebbfb0b0326d2212735490287";System.out.println(SMutil.sm2decrypt("00C1C7D8BF35BA59F4F0B28959EBBB1AAE6606140AAEAC4C379A8D57CCA508D16D", str2));}
}

所以在java代码层面的加密和解密的代码只需要调用SMHandler这个工具类即可,代码如下:

//加密---begin
if(StringUtil.isNotEmpty(role.getRoleName())){String name = sMHandler.passWordEnryptBySM2(role.getRoleName());if(StringUtil.isEmpty(name)){return new CommResponse(false,"操作失败");}else{role.setRoleName(name);}
}
//加密---end
//解密---begin
if(StringUtil.isNotEmpty(role.getRoleName())){String name = sMHandler.passWordDecryptBySM2(role.getRoleName());if(StringUtil.isEmpty(name)){return new CommResponse(false,"操作失败");}else{role.setRoleName(name);}
}
//解密---end

接下来就是JS层面的加密解密,首先我们先找到sm.js这个文件,在里面写三个function方法,获取公钥私钥和加密解密,当然你也可以自己创建一个新的js文件,代码如下:

function getSm2pubkeyHex() {var pubkey = '04509AEB08F6645C6AC92B965A5EAA6EE7761908A4AE1454DA537A855F1ADF0D611D45486362D856D7DFB45688EC969B96FD32E5E008FFE9E74E4A424A422DF3AC'return  pubkey;
}
function getSm2prikeyHex() {var prikey = '24F2401757F59665DED44ECEC08C7314E14F74E95B0720D0FA03E7992440CF1A'return  prikey ;
}
function SMutil()
{this.sm2encrypt = function(data, publickey){var msgData = CryptoJS.enc.Utf8.parse(data);var pubkeyHex = publickey;if (pubkeyHex.length > 64 * 2) {pubkeyHex = pubkeyHex.substr(pubkeyHex.length - 64 * 2);}var xHex = pubkeyHex.substr(0, 64);var yHex = pubkeyHex.substr(64);var cipher = new SM2Cipher("0");var userKey = cipher.CreatePoint(xHex, yHex);msgData = cipher.GetWords(msgData.toString());var encryptData = cipher.Encrypt(userKey, msgData);return '04' + encryptData;}this.sm3encrypt = function(str){var sm3 = new window.SM3Digest();str = new SM2Cipher().GetWords(CryptoJS.enc.Utf8.parse(str).toString());sm3.BlockUpdate(str,0,str.length);var md = new Array(32);sm3.DoFinal(md, 0);var words = [ ];var j = 0;for (var i = 0; i < md.length * 2; i += 2) {words[i >>> 3] |= parseInt(md[j]) << (24 - (i % 8) * 4);j++;}var encryptData = new CryptoJS.lib.WordArray.init(words, md.length).toString();return encryptData;}this.sm2Decrypt = function(privateKey,encrypted) {encrypted = encrypted.substr(2);var privKey = new BigInteger(privateKey, 16);var cipher = new SM2Cipher("0");var decryptData = cipher.Decrypt(privKey, encrypted);return decryptData;}

那我们在js中加密解密方法就只需要调用sm文件里面这个方法即可,代码如下:

//加密---beginvar smutil = new SMutil();var pubkey = smutil.getSm2pubkeyHex();smutil.sm2encrypt(str, pubkey);
//加密---end
//解密---beginvar smutil = new SMutil();var prikey = smutil.getSm2prikeyHex();smutil.sm2Decrypt(prikey, str);
//解密---end

因为公钥和私钥在前端和后端的一致性,所以前端加密的数据可以在后端解密,后端加密的数据也可以在前端解密。这就是最简单快捷的国密SM2加密解密,当然我的方法中还有sm3和sm2混合加密解密,sm4加密解密,我就不一一介绍了

安全扫描:敏感数据加密传输和保存(国密)相关推荐

  1. 基于国密算法实现主机之间的密钥分发和安全传输-2021西北工业大学网络空间安全学院暑期夏令营

    2021年西北工业大学网络空间安全学院暑期夏令营 一.设计内容与要求: 二.基本思路与实现: 三.设计原理与流程: 3.1 总体流程: 3.2 设计原理: 3.2.1 建立套接字连接: 3.2.2 根 ...

  2. Android 和 PHP 之间进行数据加密传输

    Android 和 PHP 之间进行数据加密传输 [代码] [Java]代码 1 mcrypt = new MCrypt(); 2 /* Encrypt */ 3 String encrypted = ...

  3. android网络传输数据加密,Android网络数据加密传输

    在移动应用开发中, 对于数据安全传输要求非常高, 尤其是涉及到用户财产安全的时候,都会对数据进行层层加密来确保数据的安全性 完整性; `在这里演示:我将演示银行在移动应用上的数据加密; 传输的数据格式 ...

  4. 支持国密/商密全数据加密型U3 U盘国产芯片方案-I560

    全数据加密U盘 如果只是采用数据存取软件锁,明文数据很容易被破解读取出来. 问题描述 如何真正做到存储数据全加密后存储?无密钥无法破解解密. 解决方案: i560 是由方寸微电子自主研发的新一代Soc ...

  5. 数据加密-国密SM2对数据进行加解密

    1 什么是SM2 RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法. SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve C ...

  6. 阿里云CDN不止于加速:基于https国密算法构建安全数据传输链路

    网络数据安全得到前所未有的重视 HTTPS成为解决传输安全问题利器 大家都知道,HTTP 本身是明文传输的,没有经过任何安全处理,网站HTTPS解决方案通过在HTTP协议之上引入证书服务,完美解决网站 ...

  7. KonaJDK 助力微服务国密算法使用特性一览

    导读 本次 TencentKona 8 版本更新到 8.0.4, 在同步到社区版本 8u272 的基础上,还有哪些新的特性呢?本文为您一一介绍: Update to jdk8u272 TencentS ...

  8. Spring Security-用户密码自定义国密SM2加密

    为什么80%的码农都做不了架构师?>>>    由于甲方要求需要把密码的加密方式改为国密SM2的方式,网上看了一些写的代码,结合了一下SpringSecurity用户自定义加密,直接 ...

  9. 奇妙的安全旅行之国密算法

    hi,大家好,我是开发者FTD.今天我们来介绍一下我们国家密码局制定的加密算法 - 国密算法. 为什么要制定国密算法? 密码算法是保障信息安全的核心技术,尤其是我国最关键的银行业核心领域长期以来都是沿 ...

最新文章

  1. node.js实现国标GB28181流媒体点播(即实时预览)服务解决方案
  2. JavaScript(3)之——对象的属性描述符
  3. 企业网络推广——企业网络推广表示合理采集可助力网站品质提升
  4. Hyperledger Fabric 链码(2) 接口
  5. 屏幕编程 F4的帮组用法
  6. 美元汇率pascal程序
  7. Codeup-问题 C: 货币系统
  8. 学习算法导论-红黑树之摘录
  9. abstract类中可以有private的成员_C++|static成员与单例模式
  10. asp sql ip地址排序_SQL必知必会读书笔记,30分钟入门SQL!
  11. linux 多线程计算pi,单/多线程计算测试:SuperPI/国际象棋_IntelCPU_CPUCPU评测-中关村在线...
  12. android自定义数字键盘
  13. 服务器之IP地址与域名之间的绑定
  14. 第四次实验任务 任务一
  15. 《别做正常的傻瓜》后续笔记—幸福的准则
  16. 微型计算机硬件组成中有哪些,计算机硬件的组成_
  17. 用html5设置国际象棋棋盘,绘制国际象棋棋盘
  18. 西北工业大学明德学院计算机老师,师资队伍结构
  19. u深度做linux启动盘,u深度启动盘制作
  20. mysql 空间数据操作,MySQL 空间数据 简单操作

热门文章

  1. 风管类型在RevitMEP中快速批量改变及管线偏移对齐
  2. restful 简单理解
  3. 【Spring 系列】Spring知识地图
  4. 深度学习-图像处理之误差传播、权重更新及优化器
  5. 展厅智能中央控制服务器,展厅智能照明管理系统-智能中央控制系统
  6. 计算机蓝屏显示的英文是什么,电脑蓝屏时会出现一堆英文,你知道是什么意思吗?...
  7. 计算机是一种工具英语,把计算机作为一种“工具”教给学生
  8. java调用r实例,Spring Boot中使用RSocket的示例代码
  9. # 2017-2018-1 20155232《信息安全技术》实验二——Windows口令破解
  10. ACMNO.45 时间转换 给定一个以秒为单位的时间t,要求用 “ H : M : S ”的格式来表示这个时间。 H 表示时间, M 表示分钟, 而 S 表示秒,它们都是整