The springboot project, mybatis custom sql+CompletableFuture, realizes batch paging and field encryption (update) according to the specified table and field

       In the process of developing projects, due to system security considerations, some sensitive data will be encrypted from time to time. Today I will share with you a batch paging reading and encrypting table fields implemented using mysql, mybatis-plus, and CompletableFuture Code logic. No nonsense, go directly to the code.

One, the first is the controller layer

package com.sf.gis.boot.realperson.controller;

import com.sf.gis.boot.realperson.service.EncryptService;
import com.sf.gis.boot.realperson.vo.JsonResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.spring.web.json.Json;

import javax.ws.rs.GET;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月03日 09:21:35
 */
@RestController
@RequestMapping("/encrypt")
@Slf4j
@Api(tags = "空间数据加密")
public class EncryptController {

    @Autowired
    private EncryptService encryptService;


    @GetMapping("/secretByTable")
    @ApiOperation("根据指定的表名和字段进行加密")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tableName", value = "指定表名(例如:person_statistic )",
                     dataType = "query"),
            @ApiImplicitParam(name = "fields", value = "需要加密字段(多个字段以逗号形式隔开,例如:wkt,geom,shape)",
                    dataType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "分页读取,每次批量加密数据的条数",
                    dataType = "query", defaultValue = "250")
    })
    public JsonResponse secretByTable(@RequestParam(value = "tableName",required = true) String tableName
            , @RequestParam(value = "fields",required = true) String fields, @RequestParam(value = "pageSize", required = true,defaultValue = "100") Integer pageSize) {
        JsonResponse jsonResponse = new JsonResponse();
        try {
            jsonResponse = encryptService.secretByTable(tableName, fields, pageSize);
        } catch (Exception e) {
            log.error("error", e);
            jsonResponse.setData(JsonResponse.STATUS_FAILED, null);
        }
        return jsonResponse;

    }


}

There is nothing to say here.

Two, write the service logic layer

package com.sf.gis.boot.realperson.service;

import com.sf.gis.boot.realperson.vo.JsonResponse;

import java.util.LinkedHashMap;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月03日 09:26:58
 */
public interface EncryptService  {

    JsonResponse secretByTable(String tableName, String fields, Integer pageSize);

}

 

package com.sf.gis.boot.realperson.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sf.gis.boot.realperson.entity.StandardAddress;
import com.sf.gis.boot.realperson.mapper.EncryptMapper;
import com.sf.gis.boot.realperson.mapper.StandardAddressMapper;
import com.sf.gis.boot.realperson.service.EncryptService;
import com.sf.gis.boot.realperson.vo.JsonResponse;
import com.sf.gis.boot.sys.entity.SysDictionary;
import com.sf.gis.boot.sys.service.SysDictionaryService;
import com.sf.gis.boot.utils.SecurtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import springfox.documentation.spring.web.json.Json;

import static com.sf.gis.boot.realperson.service.impl.EncryptServiceImpl.EncryptTablesEnum.*;
import static com.sf.gis.boot.realperson.vo.JsonResponse.STATUS_FAILED;
import static com.sf.gis.boot.realperson.vo.JsonResponse.STATUS_SUCCESS;


import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月03日 09:27:57
 */
@Service
@Slf4j
public class EncryptServiceImpl implements EncryptService {

    @Autowired
    private EncryptMapper encryptMapper;


    private String key = "";


    @Override
    public JsonResponse secretByTable(String tableName, String fields, Integer pageSize) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        final JsonResponse jsonResponse = new JsonResponse();
        if (StringUtils.isBlank(tableName)) {
            jsonResponse.setData(JsonResponse.STATUS_FAILED, false, "表明不能为空");
            return jsonResponse;
        }
        if (StringUtils.isBlank(fields)) {
            jsonResponse.setData(JsonResponse.STATUS_FAILED, false, "字段不能为空");
            return jsonResponse;
        }

        fields = StringUtils.deleteWhitespace(fields).replaceAll(",", ",");

        if (AOI.getTableName().equals(tableName)) {
            fields = fields.replaceAll("wkt", "st_astext(wkt) as wkt");
        }
        if (PERSON_STATISTIC.getTableName().equals(tableName)) {
            fields = fields.replaceAll("geom", "st_astext(geom) as geom");
        }

        SysDictionary dictByPathKey = sysDictionaryService.getDictByPathKey("PersonDataEncrypt", "extInfoKey");
        key = dictByPathKey.getDicValue();

        //从第一页开始读取
        Page pageParam = new Page(0, pageSize);
        //拼接查询sql语句
        String id = AOI.getTableName().equals(tableName) ? "aoi_id," : "id,";
        //String orderBy = AOI.getTableName().equals(tableName)?" order by aoi_id asc":" order by id";

        StringBuilder sqlBuilder = new StringBuilder("select " + id);
        sqlBuilder.append(fields).append(" from ").append(tableName);
        //.append(orderBy);

        Page<LinkedHashMap<String, Object>> page = encryptMapper.encryptByTable(pageParam, sqlBuilder.toString());

        List<LinkedHashMap<String, Object>> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            //第一页数据进行加密
//          encryptAndUpdate(tableName, records);
            CompletableFuture.runAsync(() -> encryptAndUpdate(tableName, records));
            //获取总记录数,计算总共需要分成多少页进行读取
            int total = (int) page.getTotal();
            int batch = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
            //从第二页开始读取数据并加密
            for (int i = 1; i <= batch; i++) {
                pageParam.setCurrent(i).setSize(pageSize);
                page = encryptMapper.encryptByTable(pageParam, sqlBuilder.toString());
                List<LinkedHashMap<String, Object>> pageRecords = page.getRecords();
                if (!CollectionUtils.isEmpty(pageRecords)) {
//                  encryptAndUpdate(tableName, pageRecords);
                    CompletableFuture.runAsync(() -> encryptAndUpdate(tableName, pageRecords));
                }
            }
            CompletableFuture.allOf();
            stopWatch.stop();
            log.info("所有任务执行完毕,总耗时{}", stopWatch.getTotalTimeMillis());
            jsonResponse.setData(STATUS_SUCCESS, true, "表字段加密成功");
            return jsonResponse;
        } else {
            jsonResponse.setData(STATUS_SUCCESS, true, "无数据");
            return jsonResponse;
        }
    }


    public static final String POLYGON_pre = "POLYGON((";
    public static final String POLYGON_suf = "))";
    public static final String linestring_pre = "linestring(";
    public static final String linestring_suf = ")";
    public static final String point_pre = "point(";
    public static final String point_suf = ")";
    public static final String MULTIPOLYGON_pre = "MULTIPOLYGON(((";
    public static final String MULTIPOLYGON_suf = ")))";


    @Autowired
    private SysDictionaryService sysDictionaryService;

    public void encryptAndUpdate(String tableName, List<LinkedHashMap<String, Object>> list) {
        List<LinkedHashMap<String, String>> result = list.parallelStream().map(x -> {
            LinkedHashMap<String, String> map = new LinkedHashMap<>(x.size());
            for (Map.Entry<String, Object> entry : x.entrySet()) {
                String k = entry.getKey();
                Object v = entry.getValue();
                if (ObjectUtil.isNotEmpty(v)) {
                    if (!"aoiId".equals(k) && !"id".equals(k)) {
                        //判断v是否是空间数据
                        String vStr = ObjectUtil.toString(v);
                        if (StringUtils.startsWithIgnoreCase(vStr, POLYGON_pre) || StringUtils.startsWithIgnoreCase(vStr, linestring_pre)
                                || StringUtils.startsWithIgnoreCase(vStr, point_pre) || StringUtils.startsWithIgnoreCase(vStr, MULTIPOLYGON_pre)) {
                            vStr = subWktForXY(vStr);
                        }
                        String secretField = SecurtUtil.secret(vStr,key);
                        map.put(k + "_encrypt", secretField);
                    } else {
                        map.put(k, ObjectUtil.toString(v));
                    }
                } else {
                    map.put(k + "_encrypt", null);
                }
            }
            return map;
        }).collect(Collectors.toList());
        //批量更新
        encryptMapper.batchUpdate(tableName, result);

//        if (AOI.getTableName().equals(tableName)) {
//            int flag = encryptMapper.batchUpdateAoi(result);
//            log.info(flag+"");
//        } else if (STANDARD_ADDRESS.getTableName().equals(tableName)) {
//            encryptMapper.batchUpdateStandardAddress(result);
//        } else if (PERSON_STATISTIC.getTableName().equals(tableName)) {
//            encryptMapper.batchUpdatePersonStatistic(result);
//        }
    }


    static enum EncryptTablesEnum {
        AOI("aoi"), STANDARD_ADDRESS("standard_address"), PERSON_STATISTIC("person_statistic");
        private String tableName;

        public String getTableName() {
            return tableName;
        }

        public void setTableName(String tableName) {
            this.tableName = tableName;
        }

        EncryptTablesEnum(String tableName) {
            this.tableName = tableName;
        }
    }


    /**
     * 截取wkt,geom,shape字段中的经纬度并进行转换
     *
     * @return
     */
    public String subWktForXY(String wkt) {
        if (StringUtils.startsWithIgnoreCase(wkt, POLYGON_pre)) {
            wkt = wkt.substring(POLYGON_pre.length(), wkt.length() - POLYGON_suf.length());
        } else if (StringUtils.startsWithIgnoreCase(wkt, linestring_pre)) {
            wkt = wkt.substring(linestring_pre.length(), wkt.length() - linestring_suf.length());
        } else if ( StringUtils.startsWithIgnoreCase(wkt, point_pre)) {
            wkt = wkt.substring(point_pre.length(), wkt.length() - point_suf.length());
        } else if ( StringUtils.startsWithIgnoreCase(wkt, MULTIPOLYGON_pre)) {
            wkt = wkt.substring(MULTIPOLYGON_pre.length(), wkt.length() - MULTIPOLYGON_suf.length());
        }
        //MULTIPOLYGON(((114.317113343627 29.8280205416181,114.318119807265 29.8280165418767,114.318269 29.828105,114.318318 29.82817,114.318345 29.828287,114.318371 29.828547,114.318398 29.828775,114.318436 29.829003,114.318543 29.829343,114.318736 29.829874,114.318754229062 29.8299751927346,114.318786723512 29.8301466508578,114.318602 29.830197,114.318436 29.83026,114.317746 29.830448,114.317572 29.830534,114.317148 29.830823,114.316928 29.83087,114.316714 29.830856,114.316408 29.830809,114.316252 29.830832,114.316134 29.830916,114.315898 29.831917,114.315845614531 29.8320052290616,114.315742192735 29.8320174217962,114.315496 29.831972,114.315078 29.8318988072654,114.314936578204 29.831829036327,114.314866 29.831686,114.314746541877 29.831558,114.314664312815 29.8312961927346,114.314643312815 29.8311128072654,114.314697734611 29.830902,114.314702 29.830767,114.314579 29.830651,114.314471 29.830614,114.314203 29.830623,114.314085 29.830569,114.31401 29.830483,114.313999 29.830372,114.314032 29.830209,114.314155 29.829855,114.314311 29.829762,114.314563 29.829674,114.314708 29.829567,114.31475 29.829436,114.314815867174 29.8289833128797,114.316784820548 29.8290955572526,114.316823689012 29.8284137396182,114.317090062874 29.8284289248265,114.317113343627 29.8280205416181)))
        //114.314719|29.845341;114.314971|29.845512;114.315188|29.845617;
        wkt = wkt.replaceAll(" ", "|").replaceAll(",|,", ";");
        return wkt;

    }

}

 The main processing logic is here. We first use a stopWatch timer that comes with spring to calculate the processing time of the entire method. The key value in the member variable is the data encryption key configured in the dictionary table in the database. First, we Need to splice a custom sql, the data read to the first page can get the total number of records from the Page object, calculate how many pages need to be divided for processing, and then use the for loop to page through the for loop to read the data, and the read data is used CompletableFuture processes encryption logic asynchronously, because data encryption logic does not require data sequence, which can speed up code execution. Finally, calling the CompletableFuture.allOf() method will block the main thread. It is convenient to calculate the total execution time. The blogger here has done a test. The execution time for 2500 pieces of data is 1 second. Of course, there is still room for optimization. Table fields are indexed, the number of data items are modified each time, and the threshold of batch data is updated.

Three, write the mapper layer

package com.sf.gis.boot.realperson.mapper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月03日 09:37:19
 */
@Mapper
@Repository
public interface EncryptMapper {


        Page<LinkedHashMap<String,Object>> encryptByTable(@Param("page") Page page, @Param("sql") String sql);

        int batchUpdate(@Param("tableName") String tableName, @Param("list") List<LinkedHashMap<String, String>> list);

        int batchUpdateAoi(@Param("list") List<LinkedHashMap<String, String>> list);

        int batchUpdateStandardAddress(@Param("list") List<LinkedHashMap<String, String>> list);

        int batchUpdatePersonStatistic(@Param("list") List<LinkedHashMap<String, String>> list);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sf.gis.boot.realperson.mapper.EncryptMapper">

    <select id="encryptByTable" resultType="java.util.LinkedHashMap" parameterType="java.lang.String">
           ${sql}
    </select>


    <update id="batchUpdate" parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" separator=";">
            update ${tableName} set
            <foreach collection="item.entrySet()" index="key" item="value" separator=",">
                <if test="key!='aoiId' and key!='id'">
                    ${key} =#{value}
                </if>
            </foreach>
            <where>
            <if test="tableName!='' and tableName!=null and tableName=='aoi'">
                aoi_id = #{item.aoiId}
            </if>
            <if test="tableName!='' and tableName!=null and tableName!='aoi'">
                id = #{item.id}
            </if>
            </where>
        </foreach>
    </update>

    <update id="batchUpdateAoi" parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" separator=";">
            update aoi
            <set>
                <if test="item.containsKey('wkt_encrypt')">
                    wkt_encrypt = #{item.wkt_encrypt},
                </if>
                <if test="item.containsKey('x_encrypt')">
                    x_encrypt = #{item.x_encrypt},
                </if>
                <if test="item.containsKey('y_encrypt')">
                    y_encrypt = #{item.y_encrypt}
                </if>
            </set>
            where aoi_id = #{item.aoiId}

        </foreach>
    </update>

    <update id="batchUpdateStandardAddress">
        <foreach collection="list" item="item" index="index" separator=";">
            update standard_address
            <set>
                <if test="item.containsKey('shape_encrypt')">
                    shape_encrypt = #{item.shape_encrypt},
                </if>
                <if test="item.containsKey('x_encrypt')">
                    x_encrypt = #{item.x_encrypt},
                </if>
                <if test="item.containsKey('y_encrypt')">
                    y_encrypt = #{item.y_encrypt}
                </if>
            </set>
            where id = #{item.id}
        </foreach>
    </update>

    <update id="batchUpdatePersonStatistic">
        <foreach collection="list" item="item" index="index" separator=";">
            update person_statistic
            <set>
                <if test="item.containsKey('geom_encrypt')">
                    geom_encrypt = #{item.geom_encrypt},
                </if>
                <if test="item.containsKey('wkt_encrypt')">
                    wkt_encrypt = #{item.wkt_encrypt},
                </if>
                <if test="item.containsKey('x_encrypt')">
                    x_encrypt = #{item.x_encrypt},
                </if>
                <if test="item.containsKey('y_encrypt')">
                    y_encrypt = #{item.y_encrypt}
                </if>
            </set>
            where id = #{item.id}
        </foreach>
    </update>


</mapper>

What needs to be said here is that the code started to use the following three sql statements to perform batch data updates for three different tables. Due to the lack of versatility, the sql of the first batchUpdate was used instead. According to the transmission The dynamic sql generated by the imported List<LinkedHashMap<String,String>>, pay attention to the table name ${tableName} and field name ${key} here, you need to use the $ symbol instead of #, otherwise an error will be reported , the blogger is in the project The reason for the pits stepped in during the development process is that # will automatically add single quotes to both sides of the parsed field, which will cause SQL execution to report an error.

Four, spatial data encryption

package com.sf.gis.boot.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Date;
import java.util.Objects;

import static java.lang.Integer.parseInt;

public class SecurtUtil {

    public static final String KEY = "82626121-5782-1454-1247-15525212";

    private static final Logger log = LoggerFactory.getLogger(SecurtUtil.class);

    private static final int NUM_EIGHT = 8;


    /**
     * 字符串转化成为16进制字符串
     *
     * @param s
     * @return
     */
    public static String strTo16(String s) {

        StringBuffer str = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);

            str.append(s4);
        }
        return str.toString();
    }

    /**
     * 16进制转换成为string类型字符串
     *
     * @param s
     * @return
     */
    public static String hexStringToString(String s) {
        if (s == null || ("").equals(s)) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                log.info(e.getMessage());
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            log.info(e1.getMessage());
        }
        return s;
    }

    public static String xor(String value, char[] secrets) {
        byte[] bt = value.getBytes();
        for (int i = 0; i < bt.length; i++) {
            if (secrets.length > i) {
                //通过异或运算进行加密
                bt[i] = (byte) (bt[i] ^ (int) secrets[i]);
            }

        }
        //将加密后的字符串保存到 newresult 变量中
        String newresult = new String(bt, 0, bt.length);
        return newresult;
    }

//    public static String xor (String value){
//        String keyValue = strTo16(key);
//        //获取异或char数组
//        char [] secrets = keyValue.toCharArray();
//        byte[] bt=value.getBytes();
//        for(int i=0;i<bt.length;i++)
//        {
//            if (secrets.length > i){
//                bt[i]=(byte)(bt[i] ^ (int)secrets[i]); //通过异或运算进行加密
//            }
//
//        }
//        String newresult=new String(bt,0,bt.length); //将加密后的字符串保存到 newresult 变量中
//        return newresult;
//    }

    public static String xor(String value, String secrets) {
        byte[] bt = null;
        byte[] btSecrets = null;
        try {
            bt = value.getBytes("utf-8");
            btSecrets = secrets.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            log.info(e.getMessage());
        }
        if (Objects.isNull(bt) || Objects.isNull(btSecrets)) {
            return "";
        }
        for (int i = 0; i < bt.length; i++) {

            if (btSecrets.length > i) {
                bt[i] = (byte) (bt[i] ^ (int) btSecrets[i]);
            }

        }
        //将加密后的字符串保存到 newresult 变量中
        String newresult = null;
        try {
            //new String(bt,"US-ASCII");
            newresult = byteToString(bt);


        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return newresult;
    }

    public static String byteToString(byte[] arr) {

        StringBuilder stringBuilder = new StringBuilder();
        byte[] aArr = arr;
        for (int i = 0; i < aArr.length; i++) {
            String one = getBinaryStrFromByte(aArr[i]);

            if (one.indexOf("1") > -1) {
                //从1开始匹配直到遇到第一个0
                one = one.substring(one.indexOf("1"));
            } else {
                one = "";
            }
            String[] v = one.split("0");
            if (v.length > 0 && one.length() == 8) {
                int bytesLength = v[0].length();
                String tmp = getBinaryStrFromByte(aArr[i]);
                String store = tmp.substring(7 - bytesLength);
                StringBuilder storeBuider = new StringBuilder();
                storeBuider.append(store);
                for (int st = 1; st < bytesLength; st++) {
                    String tmp2 = getBinaryStrFromByte(aArr[st + i]);

                    storeBuider.append(tmp2);
                }

                stringBuilder.append(fromCharCode(parseInt(store, 2)));
                i += bytesLength - 1;
            } else {

                stringBuilder.append(fromCharCode(aArr[i]));
            }
        }

        return stringBuilder.toString();
    }

    public static String fromCharCode(int i) {
        String strValue = "" + (char) i;
        return strValue;
    }

    public static String getBinaryStrFromByte(byte b) {

        StringBuffer result = new StringBuffer();
        byte a = b;
        ;
        for (int i = 0; i < NUM_EIGHT; i++) {
            byte c = a;
            //每移一位如同将10进制数除以2并去掉余数。
            a = (byte) (a >> 1);
            a = (byte) (a << 1);
            if (a == c) {
                result.insert(0, "0");

            } else {

                result.insert(0, "1");
            }
            a = (byte) (a >> 1);
        }
        return result.toString();
    }

    public static String byteArr2HexStr(byte[] arrB) throws Exception {

        int iLen = arrB.length;

        // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
        StringBuffer sb = new StringBuffer(iLen * 2);

        for (int i = 0; i < iLen; i++) {
            int intTmp = arrB[i];
            // 把负数转换为正数
            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }

            // 小于0F的数需要在前面补0
            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16));
        }
        return sb.toString();
    }

    public static String secret(String value, String keyService) {


        String valueTemp = strTo16(value);
        String keyserviceTemp = strTo16(keyService);
        String secretStr = xor(valueTemp, keyserviceTemp);

        String finalStr = new StringBuilder(secretStr).reverse().toString();
        return finalStr;

    }

    public static String AES128Encrypt(String origin) {

        byte[] encrypted = null;
        try {
            byte[] keyArray = KEY.getBytes("utf-8");
            //设置密钥规范为AES
            SecretKeySpec skeySpec = new SecretKeySpec(keyArray, "AES");
            //"算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            encrypted = cipher.doFinal(origin.getBytes());
        } catch (InvalidKeyException | NoSuchAlgorithmException |
                NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException
                | UnsupportedEncodingException e) {
            log.error(e.getMessage());
            return null;
        }
        //此处使用BASE64做转码功能
        return new BASE64Encoder().encode(encrypted);
    }

    public static String AES128Decrypt(String secret) {

        try {
            //参数类型
            byte[] raw = new byte[0];
            raw = KEY.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            //"算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(secret);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString;
        } catch (NoSuchAlgorithmException | NoSuchPaddingException |
                InvalidKeyException |
                IOException | IllegalBlockSizeException | BadPaddingException e) {
            log.error(e.getMessage());
            return null;
        }

    }


    public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
        Date date1 = new Date();
        String extinfo = "MULTIPOLYGON(((114.322460023686 29.8905738218866, 114.322771159932 29.8898436378937, 114.323908416554 29.890187801716, 114.323774306104 29.8905738218866, 114.323913780972 29.8906528860745, 114.323860136792 29.8908296175617, 114.323420254514 29.8908947290833, 114.322460023686 29.8905738218866)))";
        String keyservice = "82626121-5782-1454-1247-617142522121";
        String result = secret(extinfo, keyservice);
        System.out.println(result);

        System.out.println(KEY.length());
        System.out.println(AES128Encrypt(keyservice));
        System.out.println(AES128Decrypt(AES128Encrypt(keyservice)));

        String encode = Base64.encode(result);

        System.out.println(encode);
        // 还原为a
        String decodeStr = Base64.decodeStr(encode);

        System.out.println(decodeStr);

    }
}

Finally, there is nothing to say about encryption tools. If you like it, please pay attention and remember to like it.

Guess you like

Origin blog.csdn.net/qq_31905135/article/details/108418383