0


SM2实现前端发送加密报文,后端解密报文

原作者在这

https://www.cnblogs.com/iroc1994/p/16399496.html

感谢原创
此文做记录使用,同时稍作修改,思路正确,内容未核验,有问题请不吝指正,后期会验证不断修改!
环境:

在工作中,前端页面发送的报文可能涉及到用户信息,为确保数据安全,需要对请求的数据加密,采用SM2非对称加密,可以有效解决数据的安全问题。

前端加密,后端解密Demo源码下载地址

https://gitee.com/iroc-git/springboot-encryptreq.git

实现步骤:

第一步:在Maven项目中引入pom依赖,注意依赖的jar包版本要在1.6以上,同时检查是否有bcprov-jdk16.*.的jar包(一般都会有),需要删掉(不放心可以先备份),否则会冲突报错

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.67</version></dependency>

第二步:生成公钥和私钥

工具类GetPKs

packagecom.iroc.springboot.util;importorg.bouncycastle.asn1.gm.GMNamedCurves;importorg.bouncycastle.asn1.x9.X9ECParameters;importorg.bouncycastle.crypto.AsymmetricCipherKeyPair;importorg.bouncycastle.crypto.generators.ECKeyPairGenerator;importorg.bouncycastle.crypto.params.ECDomainParameters;importorg.bouncycastle.crypto.params.ECKeyGenerationParameters;importorg.bouncycastle.crypto.params.ECPrivateKeyParameters;importorg.bouncycastle.crypto.params.ECPublicKeyParameters;importorg.bouncycastle.math.ec.ECPoint;importorg.bouncycastle.util.encoders.Hex;importjava.math.BigInteger;importjava.security.SecureRandom;//获取sm2公钥与私钥publicclassGetPKs{publicstaticvoidmain(String[] args){try{X9ECParameters sm2ECParameters =GMNamedCurves.getByName("sm2p256v1");ECDomainParameters domainParameters =newECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());ECKeyPairGenerator keyPairGenerator =newECKeyPairGenerator();
            keyPairGenerator.init(newECKeyGenerationParameters(domainParameters,SecureRandom.getInstance("SHA1PRNG")));AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();//上面的代码都是直接用maven依赖中的包直接import就可以用了//还有一些更底层的写法,可以自己搜索一下,图方便的这个挺好的//私钥,16进制格式,自己保存BigInteger privatekey =((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();String privateKeyHex = privatekey.toString(16);System.out.println("private Key :"+ privateKeyHex);//公钥,16进制格式,发给前端ECPoint ecPoint =((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();String publicKeyHex =Hex.toHexString(ecPoint.getEncoded(false));System.out.println("Public Key :"+ publicKeyHex);}catch(Exception e){
            e.printStackTrace();}}}

执行后:

privateKey:5e3dcfb19758d7829ebce1ee4276f8193951e0cb77040a319403fce5231cab0e
PublicKey:045417fe9233682d37355d2f64db75fb6ff1146efb68cf409cdd64bb7e31a448047c337b0edd919501f678181a230d91e621029bc64faf7fca3631ac2c869673b9

第三步:在前端页面中对请求数据加密

1.引入crypto-js.js和sm2.js

请在github中下载(https://github.com/Saberization/SM2)
下载这两个文件放到项目对应的位置
在这里插入图片描述2.对请求报文加密

//sm2公钥var pubkeyHex ="045417fe9233682d37355d2f64db75fb6ff1146efb68cf409cdd64bb7e31a448047c337b0edd919501f678181a230d91e621029bc64faf7fca3631ac2c869673b9";//对请求报文加密
jsonReqParams=sm2Encrypt(jsonReqParams, pubkeyHex,0);

前端页面login.html完整的代码

<!DOCTYPE html><head><meta charset="utf-8"/><script src="../js/crypto-js.js"></script><script src="../js/sm2.js"></script><script src="../js/jquery-3.4.1.min.js"></script><script>

        $(document).ready(function (){
            $("#submit").click(function (){var username = $("#username").val();var password = $("#password").val();var jsonReqParams ={};
                jsonReqParams.username=username;
                jsonReqParams.password=password;
                jsonReqParams=JSON.stringify(jsonReqParams);//sm2公钥var pubkeyHex ="045417fe9233682d37355d2f64db75fb6ff1146efb68cf409cdd64bb7e31a448047c337b0edd919501f678181a230d91e621029bc64faf7fca3631ac2c869673b9";//对请求报文加密
                jsonReqParams=sm2Encrypt(jsonReqParams, pubkeyHex,0);//发送请求到后端
                $.ajax({
                    type:'POST',//方法类型
                    dataType:'json',//预期服务器返回的数据类型
                    url:'/login',//请求地址
                    data:{ 'jsonReqParams': jsonReqParams },
                    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
                    success: function (data){if(data.code =="1001"){
                            $("#result").html("登录成功");}elseif(data.code=="1002"){
                            $("#result").html("登录失败");}else{
                            $("#result").html("出现异常,请联系管理员");}},
                    error: function (){
                        $("#result").html("出现异常,请联系管理员");},});});});</script></head><body>

    用户名:<input type="text" id="username"/><br />
    密码:<input type="password" id="password"/><br /><button id="submit">登录</button><br /><span id="result"></span></body>

第四步:后端接收前端的请求报文,并解密

1.在后端引入解密工具类DecryptUtil.java

packagecom.iroc.springboot.util;importorg.apache.tomcat.util.codec.binary.Base64;importorg.bouncycastle.asn1.gm.GMNamedCurves;importorg.bouncycastle.asn1.x9.X9ECParameters;importorg.bouncycastle.crypto.engines.SM2Engine;importorg.bouncycastle.crypto.params.ECDomainParameters;importorg.bouncycastle.crypto.params.ECPrivateKeyParameters;importorg.bouncycastle.util.encoders.Hex;importjava.math.BigInteger;//解密前端页面的请求报文publicclassDecryptUtil{publicstaticStringdecrypt(String cipherData)throwsException{byte[] cipherDataByte =Hex.decode(cipherData);//sm2私钥String privateKey ="5e3dcfb19758d7829ebce1ee4276f8193951e0cb77040a319403fce5231cab0e";BigInteger privateKeyD =newBigInteger(privateKey,16);X9ECParameters sm2ECParameters1 =GMNamedCurves.getByName("sm2p256v1");ECDomainParameters domainParameters1 =newECDomainParameters(sm2ECParameters1.getCurve(), sm2ECParameters1.getG(), sm2ECParameters1.getN());ECPrivateKeyParameters privateKeyParameters =newECPrivateKeyParameters(privateKeyD, domainParameters1);//用私钥解密SM2Engine sm2Engine =newSM2Engine();
        sm2Engine.init(false, privateKeyParameters);//processBlock得到Base64格式,记得解码byte[] arrayOfBytes =Base64.decodeBase64(sm2Engine.processBlock(cipherDataByte,0, cipherDataByte.length));//得到明文:SM2 Encryption TestString data =newString(arrayOfBytes);return data;}}

2.解密前端请求的报文

packagecom.iroc.springboot.controller;importcom.google.gson.JsonObject;importcom.google.gson.JsonParser;importcom.iroc.springboot.util.DecryptUtil;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.*;@ControllerpublicclassLoginController{@RequestMapping(value ="/login",method =RequestMethod.POST)@ResponseBodypublicStringlogin(@RequestParam(value ="jsonReqParams")String jsonReqParams){JsonObject result =newJsonObject();//设数据库中username为zhangsan,password为123456try{//解密前端请求的报文
            jsonReqParams =DecryptUtil.decrypt(jsonReqParams);JsonObject jsonObject =newJsonParser().parse(jsonReqParams).getAsJsonObject();String username = jsonObject.get("username").getAsString();String password = jsonObject.get("password").getAsString();if("zhangsan".equals(username)&&"123456".equals(password)){
                result.addProperty("code","1001");
                result.addProperty("desc","登录成功");}else{
                result.addProperty("code","1002");
                result.addProperty("desc","账号或密码有误");}}catch(Exception e){
            e.printStackTrace();
            result.addProperty("code","1003");
            result.addProperty("desc","出现异常,请联系管理员");}return result.toString();}}

参考文章

  1. https://blog.csdn.net/python_small_pan/article/details/120064529
  2. https://github.com/Saberization/SM2
  3. https://blog.51cto.com/boytnt/2503384

本文转载自: https://blog.csdn.net/m0_46364149/article/details/125885586
版权归原作者 Xfei0314 所有, 如有侵权,请联系我们删除。

“SM2实现前端发送加密报文,后端解密报文”的评论:

还没有评论