springbootプロジェクトmybatiscustom sql + CompletableFutureは、指定されたテーブルとフィールドに従ってバッチページングとフィールド暗号化(更新)を実現します

       プロジェクトの開発プロセスでは、システムセキュリティの考慮事項により、一部の機密データが随時暗号化されます。本日は、mysql、mybatis-plus、およびCompletableFutureCodeロジックを使用して実装されたテーブルフィールドの読み取りと暗号化のバッチページングを共有します。 。ナンセンスではありません。コードに直接アクセスしてください。

1つは、1つ目はコントローラーレイヤーです。

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;

    }


}

ここで言うことは何もありません。

2つ目は、サービスロジックレイヤーを作成することです。

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;

    }

}

 主な処理ロジックはこちらです。まず、Springに付属のstopWatchタイマーを使用して、メソッド全体の処理時間を計算します。メンバー変数のキー値は、データベースの辞書テーブルで構成されたデータ暗号化キーです。カスタムSQLをスプライスする必要があります。最初のページに読み取られたデータは、Pageオブジェクトからレコードの総数を取得し、処理のために分割する必要のあるページ数を計算してから、forループを使用してforループを通過します。データ暗号化ロジックはデータシーケンスを必要としないため、CompletableFutureは暗号化ロジックを非同期的に処理し、コードの実行を高速化できます。最後に、CompletableFuture.allOf()メソッドを呼び出すと、メインスレッドがブロックされます。合計実行時間を計算すると便利です。ここでブロガーはテストを行い、2500個のデータの実行時間は1秒です。もちろん、最適化の余地があり、テーブルフィールドにインデックスが付けられ、各クエリのデータアイテムの数が変更され、データはバッチで更新されます。

3、マッパーレイヤーを書く

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>

ここで言う必要があるのは、コードが次の3つのSQLステートメントを使用して、3つの異なるテーブルのバッチデータ更新を実行し始めたことです。汎用性がないため、代わりに最初のbatchUpdateのSQLが使用されました。インポートされたList <LinkedHashMap <String、String >>によって生成された動的SQL 、ここではテーブル名$ {tableName}とフィールド名$ {key}に注意してください。#の代わりに$記号を使用する必要があります。そうしないと、エラーが発生します。報告されると、ブロガーはプロジェクトに参加します。開発プロセス中にピットがステップインされた理由は、#解析されたフィールドの両側に一重引用符が自動的に追加され、SQL実行でエラーが報告されるためです。

4、空間データ暗号化

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);

    }
}

最後に、暗号化ツールについては何も言うことはありません。あなたがそれを好きなら、注意を払い、それを好きになることを忘れないでください。

おすすめ

転載: blog.csdn.net/qq_31905135/article/details/108418383