Эх сурвалжийг харах

加密 rsa 数据过长报错修正

andy 1 жил өмнө
parent
commit
115d9f593d

+ 8 - 0
pom.xml

@@ -31,6 +31,14 @@
             <artifactId>mysql-connector-j</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/cn.com.kingbase/kingbase8 -->
+        <dependency>
+            <groupId>cn.com.kingbase</groupId>
+            <artifactId>kingbase8</artifactId>
+            <version>8.6.0</version>
+            <scope>runtime</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>

+ 3 - 3
src/main/java/com/scbfkj/uni/library/DataEncryptionUtil.java

@@ -157,12 +157,12 @@ public class DataEncryptionUtil {
     }
 
     public static String encryptRSAByPublicKey(@Nonnull String data) throws Exception {
-        //返回base64编码后的字符串
-        return Base64.getEncoder().encodeToString(doFinalByKeyStr(0, data.getBytes(), publicKeyStr, TYPE, ALGORITHM, Cipher.ENCRYPT_MODE));
+
+        return RsaUtils.encrypt(data, publicKeyStr);
     }
 
     public static String decryptRSAByPrivateKey(@Nonnull String data) throws Exception {
-        return new String(doFinalByKeyStr(1, Base64.getDecoder().decode(data), privateKeyStr, TYPE, ALGORITHM, Cipher.DECRYPT_MODE));
+        return RsaUtils.decrypt(data, privateKeyStr);
     }
 
     /**

+ 114 - 0
src/main/java/com/scbfkj/uni/library/RsaUtils.java

@@ -0,0 +1,114 @@
+package com.scbfkj.uni.library;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.ArrayUtils;
+
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class RsaUtils {
+
+    // RSA最大加密明文大小
+    private static final int MAX_ENCRYPT_BLOCK = 117;
+
+    // RSA最大解密密文大小
+    private static final int MAX_DECRYPT_BLOCK = 128;
+
+    private RsaUtils() {
+    }
+
+    /**
+     * 获取公钥和私钥对,key为公钥,value为私钥
+     *
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static Map<String, String> genKeyPair() throws NoSuchAlgorithmException {
+        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
+        keyPairGen.initialize(1024, new SecureRandom());
+        KeyPair keyPair = keyPairGen.generateKeyPair();
+        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
+        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
+        String publicKeyString = null;
+        String privateKeyString = null;
+
+        publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()), StandardCharsets.UTF_8);
+        privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()), StandardCharsets.UTF_8);
+
+        Map<String, String> keyPairMap = new HashMap<>();
+        keyPairMap.put("publicKey", publicKeyString);
+        keyPairMap.put("privateKey", privateKeyString);
+        return keyPairMap;
+    }
+
+    public static String encrypt(String str, String publicKey) throws Exception {
+        byte[] decoded = Base64.decodeBase64(publicKey);
+        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
+                .generatePublic(new X509EncodedKeySpec(decoded));
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(1, pubKey);
+        // 分段加密
+        // URLEncoder编码解决中文乱码问题
+        byte[] data = URLEncoder.encode(str, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8);
+        // 加密时超过117字节就报错。为此采用分段加密的办法来加密
+        byte[] enBytes = null;
+        for (int i = 0; i < data.length; i += MAX_ENCRYPT_BLOCK) {
+            // 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码
+            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + MAX_ENCRYPT_BLOCK));
+            enBytes = ArrayUtils.addAll(enBytes, doFinal);
+        }
+        String outStr = Base64.encodeBase64String(enBytes);
+        return outStr;
+    }
+
+    /**
+     * 公钥分段解密
+     *
+     * @param str
+     * @param privateKey
+     * @return
+     * @throws Exception
+     */
+    public static String decrypt(String str, String privateKey) throws Exception {
+        // 获取公钥
+
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(java.util.Base64.getDecoder().decode(privateKey.getBytes()));
+        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
+                .generatePrivate(pkcs8EncodedKeySpec);
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(2, priKey);
+        byte[] data = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
+
+        // 返回UTF-8编码的解密信息
+        int inputLen = data.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] cache;
+        int i = 0;
+        // 对数据分段解密
+        while (inputLen - offSet > 0) {
+            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
+                cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);
+            } else {
+                cache = cipher.doFinal(data, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            i++;
+            offSet = i * 128;
+        }
+        out.close();
+        return URLDecoder.decode(out.toString(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+    }
+
+}
+

+ 12 - 12
src/main/java/com/scbfkj/uni/library/script/DatabaseScriptUtil.java

@@ -17,7 +17,6 @@ public class DatabaseScriptUtil {
     private static final List<String> events = new ArrayList<>();
     private static final Pattern regExpression = Pattern.compile("(?<=《)([^》]+)?(?=》)");//提取书名号变量的正则表达式
     private static final Map<String, List<String>> sqlStrVarList = new HashMap<>();//SQL语句的书名号变量列表
-    private static final DataBase DATABASE = new DataBase();
     public static Map<String, String> sqlStrNewSQL = new HashMap<>();//SQL语句更换书名号变量后的可执行SQL
 
     static {
@@ -29,6 +28,8 @@ public class DatabaseScriptUtil {
         events.add("7");
     }
 
+    private final DataBase DATABASE = new DataBase();
+
     public static Pageable pageable(Map<String, Object> args) {
         Object page = args.get("page");
         Object size = args.get("size");
@@ -90,10 +91,12 @@ public class DatabaseScriptUtil {
 
         sql = sql.replaceAll("(\\r)?\\n", " ");
         String filterLineWhereStr = null;
-        for (Object f : filterLines) {
-            Map<String, Object> it = ((Map<String, Object>) f);
-            Object comparator = it.get("comparator");
-            filterLineWhereStr = " %s %s %s %s %s %s %s %s ".formatted(filterLineWhereStr, it.getOrDefault("left", ""), it.get("column"), comparator, Objects.equals(comparator, " is null ") ? "" : "?", !Objects.equals(comparator, " is null ") ? " " : it.get("value"), it.getOrDefault("right", ""), it.getOrDefault("connector", ""));
+        if (Objects.nonNull(filterLines)) {
+            for (Object f : filterLines) {
+                Map<String, Object> it = ((Map<String, Object>) f);
+                Object comparator = it.get("comparator");
+                filterLineWhereStr = " %s %s %s %s %s %s %s %s ".formatted(filterLineWhereStr, it.getOrDefault("left", ""), it.get("column"), comparator, Objects.equals(comparator, " is null ") ? "" : "?", !Objects.equals(comparator, " is null ") ? " " : it.get("value"), it.getOrDefault("right", ""), it.getOrDefault("connector", ""));
+            }
         }
         if (Objects.nonNull(filterLineWhereStr)) {
             sql = " %s %s and %s ".formatted(sql, sql.contains(" where ") ? " 1 = 1" : " where ", filterLineWhereStr);
@@ -134,7 +137,7 @@ public class DatabaseScriptUtil {
             }
 
             if (pageable != null) {
-                newSql = "%s limit %d,%d ".formatted(newSql, pageable.page * pageable.pageSize, pageable.pageSize);
+                newSql = "%s limit %d offset %d ".formatted(newSql, pageable.pageSize, pageable.page * pageable.pageSize);
             }
             return DATABASE.queryBatch(connectionStr, newSql, result.stream().map(List::toArray).toList());
         }
@@ -211,7 +214,7 @@ public class DatabaseScriptUtil {
             sql = "select %s from (%s) as T".formatted(String.join(",", filterColumns), sql);
 
             if (pageable != null && !sql.contains(" limit ")) {
-                sql = "%s limit %d,%d ".formatted(sql, pageable.page * pageable.pageSize, pageable.pageSize);
+                sql = "%s limit %d offset %d ".formatted(sql, pageable.pageSize, pageable.page * pageable.pageSize);
             }
             List<Map<String, Object>> queryResult = DATABASE.queryBatch(connectionStr, sql, Collections.singletonList(dbFilter.toArray()));
             return UniReturnUtil.success(queryResult);
@@ -284,10 +287,10 @@ public class DatabaseScriptUtil {
         List<String> valueNames = null;
         List<String> filterNames = null;
 
-        List<String> allColumns = DATABASE.getColumnsByTableName(connectionStr, expression);
 
 //            查询
         if (Objects.equals("0", event)) {
+            List<String> allColumns = DATABASE.getColumnsByTableName(connectionStr, expression);
 
             if (filterColumns.isEmpty()) {
 //                列权限为空直接返回空数据
@@ -346,11 +349,9 @@ public class DatabaseScriptUtil {
                     values.add(filterNames.stream().map(o1::get).toArray());
                 }
             }
-
-
             expression = "select %s from (%s) as T".formatted(String.join(",", filterColumns), expression);
             if (pageable != null) {
-                expression = "%s limit %d,%d ".formatted(expression, pageable.page * pageable.pageSize, pageable.pageSize);
+                expression = "%s limit %d offset %d ".formatted(expression, pageable.pageSize, pageable.page * pageable.pageSize);
             }
             List<Map<String, Object>> result = DATABASE.queryBatch(connectionStr, expression, values);
 
@@ -456,7 +457,6 @@ public class DatabaseScriptUtil {
                     map = ((Map<?, ?>) v.get(0));
                 } else if (valueObj instanceof List<?> v) {
                     map = ((Map<?, ?>) v.get(0));
-
                 } else if (valueObj instanceof Map<?, ?> v) {
                     map = v;
                 }

+ 10 - 2
src/main/java/com/scbfkj/uni/process/DataBase.java

@@ -331,14 +331,15 @@ public class DataBase {
             return columns.get(connection + tableName);
         }
         ResultSet resultSet;
+        ResultSetMetaData metaData;
         try (Connection conn = getDataSourcePool(connection).getConnection();
-             PreparedStatement preparedStatement = conn.prepareStatement("select * from %s limit 0,1".formatted(tableName))) {
+             PreparedStatement preparedStatement = conn.prepareStatement("select * from %s limit 1 offset 0".formatted(tableName))) {
             resultSet = preparedStatement.executeQuery();
+            metaData = resultSet.getMetaData();
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
         ArrayList<String> names = new ArrayList<>();
-        ResultSetMetaData metaData = resultSet.getMetaData();
         for (int i = 0; i < metaData.getColumnCount(); i++) {
             names.add(metaData.getColumnName(i + 1));
         }
@@ -351,6 +352,13 @@ public class DataBase {
         List<Map<String, Object>> result = new ArrayList<>();
         while (resultSet.next()) {
             Map<String, Object> resultMap = new HashMap<>();
+            if (cs.isEmpty()) {
+                ResultSetMetaData metaData = resultSet.getMetaData();
+                for (int i = 0; i < metaData.getColumnCount(); i++) {
+                    cs.add(metaData.getColumnName(i + 1));
+                }
+                columns.put(connection + sql, cs);
+            }
             for (String name : cs) {
                 Object object = resultSet.getObject(name);
                 resultMap.put(name, object);

+ 2 - 0
src/main/java/com/scbfkj/uni/service/SecurityService.java

@@ -501,6 +501,7 @@ public class SecurityService {
                            labelcode,
                            selected,
                            charttype,
+                           easysearch,
                           triggerserviceid,
                            null as insetcolumnlist,
                            null as updatecolumnlist,
@@ -559,6 +560,7 @@ public class SecurityService {
                            t3.selected,
                           t3.triggerserviceid,
                           t3.charttype,
+                          t3.easysearch,
                            insetcolumnlist,
                            updatecolumnlist,
                            selectcolumnlist,

+ 8 - 0
src/main/resources/application-kinbase8.properties

@@ -0,0 +1,8 @@
+db.center.config=A0SelKtVJgLGot4XrMTnjv3/4KIKHcZb6tEXvLSqTown42q25BPSHsINRg42mrF8J2/vbwsQQtJWDs4DKVqc2kRkenu21FuOCuqmGxlINY7tBQxyJykK7IJ3Ovn7N7bsaX0PNnEcTgmNQpGrHxIgAc3uK1PYeZ1rTKMqlhNd+Jd6EMDvYPrsH/EtxrusM1s4S/BgKiOwSy7nUCjFlpczzxLJqRuQF8Ylz7ZqcNKkwsE78JOOOh/sPuTevO/6MkAGx+6T9/99M0RnGf2P9tegcKA0ioeTfzfqjAoUx74AzdozjLiPF0wqMJvICeAxHO0MQMYEqbDxXJ7dMBsu5fYyLxyTUKVsR17FIY3CiqlUsX2y2IlU/RqkaGJmZby5G2Tf5HkJm8Af3v4588BydS0pVwQXwPhdQ3yRnUAtOOw+OEqxkr/NNwoD1xTDKXJYIFG4o7rg2yvF5BCly4txXf1jPEpMAbjFc0tzorFq/D7+qY2Eno1HmVzg7PfchDyys2Ji
+db.security.config=RGIZkxRktnDmJuGudHR1OwH2bEAi0vv/Yoi/0P8WasTDLKdCxtNlq4djWqP+y19BmwZ1WZC0oeqRll9venaZ9+V0O0Msy1u8FcUa0wEOENJnN2DLxDyH/nRSdHkAMdre6XSKcI8VHc+Jb1rM0gaylJmQ8NOrr9xjQlWxwyB3w9OevGe72sUNvLf9YOLcm5iGgLmciU/BLJjrGjJuAoWgIU30n89HhvJJAmjSGGXJC1V9ecP7TwNG0rtRnL23tsw9N47pJjKqJjnFFuU+jJG0EkjzzoIJETzrqiJQ/cYtSI0w3HXjQp2dSx6iIRZ7EyIRKdUhevbTHp8bCkP9o5YQOD7gf3ASYTdTRpkTBdy/HsTIf81wTHRyCWTnSgmuXsqRdvG453Uxl27QDF0Z79K2lIzqBPs8HZwztiqMDt6dOLvsob4Vbv2bLzXhHkCLauFNhfsgtDhUUPBt+GNj/IfUySwDI+8bxSdX1iIoHcNvd5NLYc4q2jQJp2hXUrk0pTFV
+#log.target=B7xSbq4imA5zapX8kEO42mU/5sA2TyF/Ba2Y/++F3z9Np7iT4ywDUkbRC4w/Xrxv1kMSR8PQMJ4dfYwc3mYj0SJJivN5A5/6hI+ZSQBabfZZrYwaIIRdM1XIk4wo1SIrSCXKzef8X6YUH70R2tnh+Uq6KNNp08KaZ2ZXM8vX5Ss=
+server.port=9500
+app.container.code=dev
+app.enable-flyway=false
+app.enable-reset-config=false
+app.security.enable=true

+ 42 - 30
src/test/java/com/scbfkj/uni/library/DataEncryptionUtilTest.java

@@ -19,41 +19,41 @@ class DataEncryptionUtilTest {
         System.out.println("private:  " + privateKeyString);
 
         String algorithm = "RSA/ECB/PKCS1Padding";
+//        String data = """
+//                 {
+//                  "jdbcUrl": "jdbc:sqlite:systemset.sqlite",
+//                  "driverClassName": "org.sqlite.JDBC"
+//                }
+//                                """;
         String data = """
-                 {
-                  "jdbcUrl": "jdbc:sqlite:systemset.sqlite",
-                  "driverClassName": "org.sqlite.JDBC"
-                }
-                                """;
+                                {
+                  "jdbcUrl": "jdbc:kingbase8://120.26.64.82:54321/systemset",
+                  "username": "root",
+                  "password": "123@bigdata",
+                  "driverClassName": "com.kingbase8.Driver"
+                }""";
         String encryptedData = DataEncryptionUtil.encryptByPublicKey(data, publicKeyString, type, algorithm);
         String decryptedData = DataEncryptionUtil.decryptRSAByPrivateKey(encryptedData);
         System.out.println(data + ": " + encryptedData);
         Assertions.assertEquals(data, decryptedData);
-        data = """
-                {
-                  "jdbcUrl": "jdbc:sqlite:uniauth.sqlite",
-                  "driverClassName": "org.sqlite.JDBC"
-                }
-                                """;
-        encryptedData = DataEncryptionUtil.encryptByPublicKey(data, publicKeyString, type, algorithm);
-        decryptedData = DataEncryptionUtil.decryptByPrivateKey(encryptedData, privateKeyString, type, algorithm);
-        System.out.println(data + ": " + encryptedData);
-        Assertions.assertEquals(data, decryptedData);
-        data = """
-                {"type": "ES","connection": "{\\"jdbcUrl\\": \\"jdbc:sqlite:log.sqlite\\",\\"driverClassName\\": \\"org.sqlite.JDBC\\"}"}
-                                                """.trim();
-        encryptedData = DataEncryptionUtil.encryptByPublicKey(data, publicKeyString, type, algorithm);
-        decryptedData = DataEncryptionUtil.decryptByPrivateKey(encryptedData, privateKeyString, type, algorithm);
-        System.out.println(data + ": " + encryptedData);
-        Assertions.assertEquals(data, decryptedData);
-//         data = "jdbc:h2:file:./center.h2";
-//         encryptedData = DataEncryption.encryptByPublicKey(data, publicKeyString, type, algorithm);
-//         decryptedData = DataEncryption.decryptByPrivateKey(encryptedData, privateKeyString, type, algorithm);
-//        System.out.println(data+": "+encryptedData);
+//        data = """
+//                {
+//                  "jdbcUrl": "jdbc:sqlite:uniauth.sqlite",
+//                  "driverClassName": "org.sqlite.JDBC"
+//                }
+//                                """;
+//        encryptedData = DataEncryptionUtil.encryptByPublicKey(data, publicKeyString, type, algorithm);
+//        decryptedData = DataEncryptionUtil.decryptByPrivateKey(encryptedData, privateKeyString, type, algorithm);
+//        System.out.println(data + ": " + encryptedData);
 //        Assertions.assertEquals(data, decryptedData);
-//        encryptedData = DataEncryption.encryptByPrivateKey(data, privateKeyString, type, algorithm);
-//        decryptedData = DataEncryption.decryptByPublicKey(encryptedData, publicKeyString, type, algorithm);
+//        data = """
+//                {"type": "ES","connection": "{\\"jdbcUrl\\": \\"jdbc:sqlite:log.sqlite\\",\\"driverClassName\\": \\"org.sqlite.JDBC\\"}"}
+//                                                """.trim();
+//        encryptedData = DataEncryptionUtil.encryptByPublicKey(data, publicKeyString, type, algorithm);
+//        decryptedData = DataEncryptionUtil.decryptByPrivateKey(encryptedData, privateKeyString, type, algorithm);
+//        System.out.println(data + ": " + encryptedData);
 //        Assertions.assertEquals(data, decryptedData);
+
     }
 
     @Test
@@ -80,12 +80,24 @@ class DataEncryptionUtilTest {
 
     @Test
     void encrypt() throws Exception {
-        String password = DataEncryptionUtil.encryptRSAByPublicKey("123!@#QWEqwe");
+        String password = DataEncryptionUtil.encryptRSAByPublicKey("""
+                                {
+                  "jdbcUrl": "jdbc:kingbase8://120.26.64.82:54321/uniauth",
+                  "username": "root",
+                  "password": "123@bigdata",
+                  "driverClassName": "com.kingbase8.Driver"
+                }
+                                """);
         System.out.println(password);
     }
 
     @Test
-    void decrypt() {
+    void decrypt() throws Exception {
+        String string = DataEncryptionUtil.decryptRSAByPrivateKey("A0SelKtVJgLGot4XrMTnjv3/4KIKHcZb6tEXvLSqTown42q25BPSHsINRg42mrF8J2/vbwsQQtJWDs4DKVqc2kRkenu21FuOCuqmGxlINY7tBQxyJykK7IJ3Ovn7N7bsaX0PNnEcTgmNQpGrHxIgAc3uK1PYeZ1rTKMqlhNd+Jd6EMDvYPrsH/EtxrusM1s4S/BgKiOwSy7nUCjFlpczzxLJqRuQF8Ylz7ZqcNKkwsE78JOOOh/sPuTevO/6MkAGx+6T9/99M0RnGf2P9tegcKA0ioeTfzfqjAoUx74AzdozjLiPF0wqMJvICeAxHO0MQMYEqbDxXJ7dMBsu5fYyLxyTUKVsR17FIY3CiqlUsX2y2IlU/RqkaGJmZby5G2Tf5HkJm8Af3v4588BydS0pVwQXwPhdQ3yRnUAtOOw+OEqxkr/NNwoD1xTDKXJYIFG4o7rg2yvF5BCly4txXf1jPEpMAbjFc0tzorFq/D7+qY2Eno1HmVzg7PfchDyys2Ji");
+        System.out.println(string);
+        string = DataEncryptionUtil.decryptRSAByPrivateKey("Jnj84d14EmSgKEXyAbSH+bratWGkpV89/VA5Er4yQOt7qlnKtGYJzBVJNNYMBdmSlW0G+nqDHMhJQcmHrwbjjChYuGeDcmKSRmvFQ9u7LwqmgEfazzKKoVawXmJ40dMsec2yaFyNnCM92xn1hzHvle5BL7x3kza2htGm+iOqO7Y=");
+        System.out.println(string);
+
     }
 
     @Test