Browse Source

feat: 12.21 管理端SM2加密

Juneh 1 year ago
parent
commit
d51a4a7960

+ 19 - 2
zhbsq-admin/src/main/java/com/hjy/web/controller/system/SysLoginController.java

@@ -5,16 +5,20 @@ import com.hjy.common.core.domain.AjaxResult;
 import com.hjy.common.core.domain.entity.SysMenu;
 import com.hjy.common.core.domain.entity.SysUser;
 import com.hjy.common.core.domain.model.LoginBody;
+import com.hjy.common.core.sm2.Sm2;
 import com.hjy.common.utils.SecurityUtils;
+import com.hjy.common.utils.Sm2Utils;
 import com.hjy.framework.web.service.SysLoginService;
 import com.hjy.framework.web.service.SysPermissionService;
 import com.hjy.system.service.ISysMenuService;
+import org.bouncycastle.crypto.InvalidCipherTextException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.security.NoSuchAlgorithmException;
 import java.util.List;
 import java.util.Set;
 
@@ -34,6 +38,8 @@ public class SysLoginController {
     @Autowired
     private SysPermissionService permissionService;
 
+    private String privateKeyHex = null;
+
     /**
      * 登录方法
      *
@@ -41,16 +47,27 @@ public class SysLoginController {
      * @return 结果
      */
     @PostMapping("/login")
-    public AjaxResult login(@RequestBody LoginBody loginBody) {
+    public AjaxResult login(@RequestBody LoginBody loginBody) throws InvalidCipherTextException {
+        String decrypt = Sm2Utils.decrypt(loginBody.getPassword(), privateKeyHex);
         AjaxResult ajax = AjaxResult.success();
         // 生成令牌
-        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+        String token = loginService.login(loginBody.getUsername(), decrypt, loginBody.getCode(),
                 loginBody.getUuid());
         ajax.put(Constants.TOKEN, token);
         return ajax;
     }
 
     /**
+     * 获取公密接口
+     */
+    @PostMapping("/genPUPRkey")
+    public AjaxResult genPUPRkey() throws NoSuchAlgorithmException {
+        Sm2 sm2 = Sm2Utils.genPUPRkey();
+        privateKeyHex = sm2.getPrivateKeyHex();
+        return AjaxResult.success(sm2.getPublicKeyHex());
+    }
+
+    /**
      * 获取用户信息
      *
      * @return 用户信息

+ 7 - 0
zhbsq-common/pom.xml

@@ -194,6 +194,13 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <!-- SM2算法工具类-->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15to18</artifactId>
+            <version>1.68</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 24 - 0
zhbsq-common/src/main/java/com/hjy/common/core/sm2/Sm2.java

@@ -0,0 +1,24 @@
+package com.hjy.common.core.sm2;
+
+
+import lombok.Data;
+
+/**
+ * Sm2
+ *
+ * @author HJY
+ */
+@Data
+public class Sm2{
+
+    /**
+     * 私钥
+     */
+    private String privateKeyHex;
+
+    /**
+     * 公钥
+     */
+    private String publicKeyHex;
+
+}

+ 139 - 0
zhbsq-common/src/main/java/com/hjy/common/utils/Sm2Utils.java

@@ -0,0 +1,139 @@
+package com.hjy.common.utils;
+
+import java.math.BigInteger;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Base64;
+
+import com.hjy.common.core.sm2.Sm2;
+import org.bouncycastle.asn1.gm.GMNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+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;
+
+/**
+ *
+ * @类名称 Sm2Utils.java
+ * @类描述 <pre>国密sm2工具类-适用于 js+java后端交互使用</pre>
+ * @作者  yw  xingsfdz@163.com
+ * @创建时间 2021年4月13日 下午1:52:56
+ * @版本 5.0.0
+ *
+ * @修改记录
+ * <pre>
+ *     版本                       修改人 		修改日期 		 修改内容描述
+ *     ----------------------------------------------
+ *     5.0.0 	yw 	2021年4月13日
+ *     ----------------------------------------------
+ * </pre>
+ */
+public class Sm2Utils {
+
+    //流程 通过后台代码生产公私钥对,公钥提供给js端用于数据加密,私钥用于js端传来的密文串解密
+    private static ECDomainParameters domainParameters = null;
+    private static final String privateKey = "80cfeb110007a9a11295b9289c4b889063f35fe66e54d53fdbb5b8aa335d665a";//生成的私钥 用来解密
+
+    /**
+     * 获取椭圆曲线
+     */
+    static {
+        //生成密钥对
+        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
+        domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
+    }
+
+    public static void main(String args[]) {
+        String text = "04be17bf6fe47da1f34a01ad0ff67901241b72d103e998f2f7cc78a004703bdfb8d2c6e3939f4f708f3a57d872d58ec5c41bbe5976666bcb01acea43f5a1c68a62cc117c24821d17c3023035641894d7c978a5521f8dc6798515550c73071f9703602e0ee490157729b648c1cc3eb929c1a0501e12a216d42461117402";
+        verification(text);
+    }
+
+
+    /**
+     *
+     * @方法名称 genPUPRkey
+     * @功能描述 <pre>生成公私钥对 公钥给别人拿去加密传输数据,私钥留个自己用来解密</pre>
+     * @作者    yw
+     * @创建时间 2021年4月13日 下午1:57:07
+     * @throws NoSuchAlgorithmException
+     */
+    public static Sm2 genPUPRkey() throws NoSuchAlgorithmException {
+        //生成密钥对
+        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+        keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));
+        AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
+
+        //私钥,16进制格式,自己保存,格式如80cfeb110007a9a11295b9289c4b889063f35fe66e54d53fdbb5b8aa335d665a
+        BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
+        String privateKeyHex = privatekey.toString(16);
+        System.out.println("私钥:" + privateKeyHex);
+
+        //公钥,16进制格式,发给前端,格式如0467e8c00b1fc2049aa006e75a7216eaf1fb42347b664ea63897917f1281427fa22254d39a3f5fd38e6773edc5eddc074dae27bfbe82d13094bfcbe6b344e89ee9
+        ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
+        String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
+        System.out.println("公钥:" + publicKeyHex);
+
+        Sm2 sm2 = new Sm2();
+        sm2.setPrivateKeyHex(privateKeyHex);
+        sm2.setPublicKeyHex(publicKeyHex);
+        return sm2;
+    }
+
+    /**
+     * 解密
+     * @方法名称 decrypt
+     * @功能描述 <pre></pre>
+     * @作者    yw
+     * @创建时间 2021年4月13日 下午2:09:59
+     * @param ciphertext
+     * @param privatekey
+     * @throws InvalidCipherTextException
+     */
+    public static String decrypt(String ciphertext, String privatekey) throws InvalidCipherTextException {
+        String cipherData = ciphertext;//JS加密产生的密文
+        byte[] cipherDataByte = Hex.decode(cipherData);//格式转换
+
+        BigInteger privateKeyD = new BigInteger(privatekey, 16);//私钥Hex,还原私钥
+        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);
+
+        //用私钥解密
+        SM2Engine sm2Engine = new SM2Engine();
+        sm2Engine.init(false, privateKeyParameters);
+
+        //processBlock得到Base64格式,记得解码
+        byte[] arrayOfBytes = Base64.getDecoder().decode(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));
+
+        //得到明文:SM2 Encryption Test
+        String mtext = new String(arrayOfBytes);
+        System.out.println(mtext);
+        return mtext;
+    }
+
+
+    /**
+     *
+     * @方法名称 verification
+     * @功能描述 <pre>js的密文校验</pre>
+     * @作者    yw
+     * @创建时间 2021年4月13日 下午2:13:07
+     * @param ciphertext
+     * @return
+     */
+    public static String verification(String ciphertext) {
+        String mtext = "";//明文
+        try {
+            mtext = decrypt(ciphertext, privateKey);
+            System.out.println("mtext:" + mtext);
+        } catch (InvalidCipherTextException e) {
+            e.printStackTrace();
+        }
+        return mtext ;
+    }
+}

+ 2 - 0
zhbsq-framework/src/main/java/com/hjy/framework/config/SecurityConfig.java

@@ -109,6 +109,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 // 业务放开接口
                 // 账号密码登录
                 .antMatchers("/au/defaultLogin/login").anonymous()
+                // 获取公钥
+                .antMatchers("/genPUPRkey").anonymous()
                 // 获取验证码
                 .antMatchers("/au/defaultLogin/getCode/**").anonymous()
                 // 账号验证码登录