【开发实践】使用AES算法加密 .sql文件

news2024/9/22 11:35:04

一、需求分析

笔者在开发遇到一个小需求,导出数据的sql文件,由于安全监管的需要,对sql文件进行加密处理。实现将sql文件进行加密,最终呈现如下效果:

二、加密文件

1、加密模块

    /**
     * AES加密算法
     *
     * @param sourceFilePath    文件路径
     * @param encryptedFilePath 目标文件路径
     * @param secretKey         密钥
     */
    public static void encrypt(String sourceFilePath, String encryptedFilePath, String secretKey) {
        try {
            // 生成密钥
            Key key = generateKey(secretKey);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);

            // 读取文件内容
            int index = 0;
            // 读取文件内容
            List<byte[]> somwFileData = getSomwFileData(sourceFilePath);
            for (byte[] bytes : somwFileData) {
                // 加密文件
                byte[] outputBytes = cipher.doFinal(bytes);
                // 保存加密后的文件
                FileOutputStream fos = new FileOutputStream(encryptedFilePath + "\\" + fileName[index++]);
                fos.write(outputBytes);
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 笔者的文件分块:

 完整加密解密类 代码:

package util;


import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author : 枫蜜柚子茶
 * @date : 2023/11/7
 */
public class FileEncryption {

    //自己导出文件的名称数组
    private static String[] fileName = {"f1", "f2", "f3", "f4", "f5", "f6"};

    /**
     * 设置文件路径
     */
    public static void setFileList(String[] strings) {
        fileName = strings;
    }

    /**
     * 获取文件的字节数据
     *
     * @param sourceFilePath 文件路径
     * @param cipher         加密器
     * @return 字节数据
     */
    private static byte[] getAllFileData(String sourceFilePath, Cipher cipher) throws IOException, IllegalBlockSizeException, BadPaddingException {
        List<byte[]> res = new ArrayList<>();
        for (String s : fileName) {
            File file = new File(sourceFilePath + s);
            if (file.exists()) {
                FileInputStream fis = new FileInputStream(file);
                byte[] inputBytes = new byte[(int) fis.available()];
                fis.read(inputBytes);
                fis.close();
                res.add(cipher.doFinal(inputBytes));
            }
        }
        return concatAll(res);
    }

    /**
     * 获取文件的分片字节数据
     *
     * @param sourceFilePath 文件路径
     * @return 字节数据
     */
    private static List<byte[]> getSomwFileData(String sourceFilePath) throws IOException, IllegalBlockSizeException, BadPaddingException {
        FileInputStream fis = new FileInputStream(new File(sourceFilePath));
        byte[] inputBytes = new byte[(int) fis.available()];
        fis.read(inputBytes);
        fis.close();
        //加密数据
        return splitArr(inputBytes, fileName.length);
    }

    /**
     * 合并字节数据
     *
     * @param list 字节数组
     * @return 单个字节数组
     */
    private static byte[] concatAll(List<byte[]> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        int totalLength = 0;
        for (byte[] bytes : list) {
            totalLength += bytes.length;
        }
        byte[] result = Arrays.copyOf(list.get(0), totalLength);
        int offset = list.get(0).length;
        for (int i = 1; i < list.size(); i++) {
            byte[] array = list.get(i);
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }
        return result;
    }

    /**
     * 对字节数组进行分片
     *
     * @param array 字节数组
     * @param num   分片数量
     * @return 分片数组
     */
    private static List<byte[]> splitArr(byte[] array, int num) {
//        System.out.println(array.length);
        int everySize = array.length / num;
        List<byte[]> arrayList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            int index = i * everySize;
            everySize = i != num - 1 ? everySize : array.length - index;
            byte[] arr = new byte[everySize];
            int j = 0;
            while (j < everySize && index < array.length) {
                arr[j] = array[index++];
                j++;
            }
            arrayList.add(arr);
        }
        return arrayList;
    }

    /**
     * AES加密算法
     *
     * @param sourceFilePath    文件路径
     * @param encryptedFilePath 目标文件路径
     * @param secretKey         密钥
     */
    public static void encrypt(String sourceFilePath, String encryptedFilePath, String secretKey) {
        try {
            // 生成密钥
            Key key = generateKey(secretKey);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);

            // 读取文件内容
            int index = 0;
            // 读取文件内容
            List<byte[]> somwFileData = getSomwFileData(sourceFilePath);
            for (byte[] bytes : somwFileData) {
                // 加密文件
                byte[] outputBytes = cipher.doFinal(bytes);
                // 保存加密后的文件
                FileOutputStream fos = new FileOutputStream(encryptedFilePath + "\\" + fileName[index++]);
                fos.write(outputBytes);
                fos.close();
            }
//            System.out.println("文件加密成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * AES解密算法
     *
     * @param sourceFilePath    文件路径
     * @param decryptedFilePath 目标文件路径
     * @param secretKey         密钥
     */
    public static void decrypt(String sourceFilePath, String decryptedFilePath, String secretKey) {
        try {
            // 生成密钥
            Key key = generateKey(secretKey);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, key);

            // 读取文件内容
            byte[] allFileData = getAllFileData(sourceFilePath, cipher);
            // 加密文件
//            byte[] outputBytes = cipher.doFinal(allFileData);
            // 保存加密后的文件
            FileOutputStream fos = new FileOutputStream(decryptedFilePath);
            fos.write(allFileData);
            fos.close();
//            System.out.println("文件解密成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 密钥对象
     *
     * @param secretKey 密钥
     * @return 对象
     */
    private static Key generateKey(String secretKey) throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        SecretKey key = new SecretKeySpec(secretKey.getBytes(), "AES");
        return key;
    }
}

三、解密文件

解密算法已在完整代码中呈现,这里不在赘述。

解密器的图形化界面代码:

import config.SystemConfig;
import util.FileEncryption;
import util.FileNameCheck;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.*;

/**
 * @author : 枫蜜柚子茶
 * @date : 2023/11/8
 */
public class EncryptFrame extends JFrame {

    // 定义组件
    JPanel jp1, jp2, jp4;
    JLabel label;
    JButton start, reset, scanFile;
    JTextField textField;
    //当前文件类
    File curr;

    // 构造函数
    public EncryptFrame() {

        EncryptFrame encryptFrame = this;

        jp1 = new JPanel();
        jp2 = new JPanel();
        jp4 = new JPanel();

        label = new JLabel("请选择文件:");

        textField = new JTextField(20);// 文本域
        textField.setEnabled(false);
        scanFile = new JButton("浏览");// 钮1

        start = new JButton("开始");
        reset = new JButton("重置");

        //设置布局为4行1列
        GridLayout layout = new GridLayout(4, 1);
        this.setLayout(layout);

        // 加入各个组件
        jp2.add(label);
        jp2.add(textField);
        jp2.add(scanFile);

        jp4.add(start);
        jp4.add(reset);

        // 加入到JFrame
        this.add(jp1);
        this.add(jp2);
        this.add(jp4);

        //设置参数
        this.setSize(500, 260);
        this.setTitle("解密器");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

        //使得窗口在屏幕中心显示
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension screenSize = kit.getScreenSize();
        this.setBounds((screenSize.width - 500) / 2, (screenSize.height - 260) / 2, 500, 260);
        //获取所选择的文件
        scanFile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser();
                chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
                JLabel jLabel = new JLabel();
                chooser.showDialog(jLabel, "选择");
                curr = chooser.getSelectedFile();
                if (curr != null) {
                    textField.setText(curr.getAbsoluteFile().toString());
                }
            }
        });
        //重置当前选择文件
        reset.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                textField.setText("");
            }
        });
        //开始处理数据
        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    String sourcePath = textField.getText() + "\\";
                    Date date = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yy年MM月dd日");
                    String decryptedFilePath = "sql\\" + format.format(date) + "数据文件.sql";
//                    System.out.println(sourcePath);
                    if (sourcePath == null || "".equals(sourcePath)) {
                        JOptionPane.showMessageDialog(encryptFrame, "文件路径不能为空!", "警告", JOptionPane.WARNING_MESSAGE);
                    } else if (!curr.exists()) {
                        JOptionPane.showMessageDialog(encryptFrame, "当前文件或者文件夹不存在!", "警告", JOptionPane.WARNING_MESSAGE);
                    } else if (curr.isFile()) {
                        JOptionPane.showMessageDialog(encryptFrame, "请选择文件夹!", "警告", JOptionPane.WARNING_MESSAGE);
                    } else if (curr.listFiles() == null || curr.listFiles().length == 0) {
                        JOptionPane.showMessageDialog(encryptFrame, "该文件夹为空!", "警告", JOptionPane.WARNING_MESSAGE);
                    } else {
                        //遍历当前文件夹下的文件
                        File[] files = curr.listFiles();
                        //收集文件名
                        Set<String> fileName = new HashSet<>();
                        for (File file : files) {
                            fileName.add(file.getName());
                        }
                        if (!FileNameCheck.checkFileName(fileName)) {
                            JOptionPane.showMessageDialog(encryptFrame, "文件不符合解密对象要求!", "警告", JOptionPane.WARNING_MESSAGE);
                        } else {
                            File target = new File("sql");
                            if (!target.exists()) {
                                target.mkdirs();
                            }
                            FileEncryption.decrypt(sourcePath, decryptedFilePath, SystemConfig.secretKey);
                            JOptionPane.showMessageDialog(encryptFrame, "解密成功,已导出到当前文件夹下!", "成功", JOptionPane.INFORMATION_MESSAGE);
                        }
                    }
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(encryptFrame, "导出错误!", "失败", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

    }
}

【运行结果】 

成功将6个乱码文件解密为 .sql文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1244967.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运动戴什么耳机好?运动无线耳机哪个品牌比较好?运动耳机推荐

​如果你是一名户外运动爱好者&#xff0c;那么一款高品质的运动耳机是必不可少的。它们具备好音质、高稳固性舒适度、防尘防水等多项防护功能&#xff0c;让你在恶劣的天气条件下也能保持音乐的陪伴。面对市面上越来越多的运动耳机&#xff0c;到底哪款更值得入手&#xff1f;…

Co-DETR:DETRs与协同混分配训练论文学习笔记

论文地址&#xff1a;https://arxiv.org/pdf/2211.12860.pdf 代码地址&#xff1a; GitHub - Sense-X/Co-DETR: [ICCV 2023] DETRs with Collaborative Hybrid Assignments Training 摘要 作者提出了一种新的协同混合任务训练方案&#xff0c;即Co-DETR&#xff0c;以从多种标…

自建私有化证书颁发机构(Certificate Authority,CA)实战之 《0x01 Nginx 配置 https单向认证》

自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;实战之 《0x01 Nginx 配置 https单向认证》 上一篇文章我们介绍了如何自建私有化证书颁发机构&#xff08;Certificate Authority&#xff0c;CA&#xff09;&#xff0c;本篇文章我们将介…

Python 使用XlsxWriter操作Excel

在数据处理和报告生成的领域中&#xff0c;Excel 文件一直是广泛使用的标准格式。为了让 Python 开发者能够轻松创建和修改 Excel 文件&#xff0c;XlsxWriter 库应运而生。XlsxWriter 是一个功能强大的 Python 模块&#xff0c;专门用于生成 Microsoft Excel 2007及以上版本&a…

ECRS生产工时分析软件:工业效率提升的隐形引擎

降本增效往往是企业开工规划的第一步。那到底降什么本&#xff0c;增什么效呢&#xff0c;对于很多企业来说&#xff0c;都是从采购成本入手&#xff0c;结果采购成本是降下来了&#xff0c;但是整体品质却下降了。实际上&#xff0c;要降本增效&#xff0c;优化现场管理才是企…

【LeetCode刷题笔记】DFSBFS(二)

994. 腐烂的橘子(树/图的BFS问题) 解题思路: 多源BFS ,首选找到 所有的腐烂的橘子 ,放入队列中,然后进行 BFS 广搜,广搜的 层数 - 1 就是所需要花费的分钟数。 在最开始先扫描一遍二维数组,将所有的 腐烂的橘子 加入 队列 ,同时统计新鲜橘子的数量 <

Java架构师发展方向和历程

目录 1 导论2 架构师的三观培养3 架构师的遇到的困难4 架构师职责5 架构师之路6 架构师的发展方向7 应用领域架构师8 业务架构师9 系统架构师和企业架构师10 技术路线和演进规划11 一线大厂的技术生态拓张案例12 如何推进项目落地想学习架构师构建流程请跳转:Java架构师系统架…

Spark-06:共享变量

目录 1.广播变量&#xff08;broadcast variables&#xff09; 2.累加器&#xff08;accumulators&#xff09; 在分布式计算中&#xff0c;当在集群的多个节点上并行运行函数时&#xff0c;默认情况下&#xff0c;每个任务都会获得函数中使用到的变量的一个副本。如果变量很…

深信服防火墙路由模式开局部署-手把手教学(小白篇)

PS&#xff1a;深信服的设备只有400能够通过console连接&#xff0c;一般用户是无法连接的&#xff0c;所以大家不要妄想着从Console连接设备了&#xff0c;开局就通过MANAGE进入Web就可以 接通电源后&#xff0c;开机拿一根网线&#xff0c;一端连接防火墙的MANAGE口&#xf…

中国毫米波雷达产业分析2——毫米波雷达产业链分析

一、产业链构成 毫米波雷达产业链分为三部分&#xff1a;上游主要包括射频前端组件&#xff08;MMIC&#xff09;、数字信号处理器&#xff08;DSP/FPGA&#xff09;、高频PCB板、微控制器&#xff08;MCU&#xff09;、天线及控制电路等硬件供应商&#xff1b;中游主体是毫米波…

Electron+VUE3开发简版的编辑器【文件预览】

简版编辑器的功能主要是: 打开对话框,选择文件后台读取文件文件前端展示文件内容。主要技术栈是VUE3、Electron和Nodejs,VUE3做页面交互,Electron提供一个可执行Nodejs的环境以及支撑整个应用的环境,nodeJS负责读取文件内容。 环境配置、安装依赖这些步骤就不再叙述了。 …

【Flink】状态管理

目录 1、状态概述 1.1 无状态算子 1.2 有状态算子 2、状态分类 ​编辑 2.1 算子状态 2.1.1 列表状态&#xff08;ListState&#xff09; 2.1.2 联合列表状态&#xff08;UnionListState&#xff09; 2.1.3 广播状态&#xff08;BroadcastState&#xff09; 2.2 按键分…

案例012:Java+SSM+uniapp基于微信小程序的科创微应用平台设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

ElementUI table+dialog实现一个简单的可编辑的表格

table组件如何实现可编辑呢&#xff1f; 我的需求是把table组件那样的表格&#xff0c;实现它点击可以弹出一个框&#xff0c;然后在这个框里面输入你的东西&#xff0c;然后将他回显回去&#xff0c;当然&#xff0c;输入的有可能是时间啥的。 为什么要弹出弹层不在框上直接…

文件名称管理文件:抓关键字归类文件,让文件管理变得简单明了

在当今数字时代&#xff0c;每天都要处理大量的文件&#xff0c;无论是文本、图片、视频还是其他类型的文件。如何有效地管理这些文件&#xff0c;能够迅速找到所需的信息&#xff0c;已经成为了一个重要的问题。文件名称是文件内容的第一反映&#xff0c;也是识别和检索文件的…

在arm 64 环境下使用halcon算法

背景&#xff1a; halcon&#xff0c;机器视觉领域神一样得存在&#xff0c;在windows上&#xff0c;应用得特别多&#xff0c; 但是arm环境下使用得很少。那如何在arm下使用halcon呢。按照官方说明&#xff0c;arm下只提供了运行时环境&#xff0c;并且需要使用价值一万多人民…

element中el-switch的v-model自定义值

一、问题 element中的el-switch的值默认都是true或false&#xff0c;但是有些时候后端接口该字段可能是0或者1&#xff0c;如果说再转换一次值&#xff0c;那就有点太费力了。如下所示&#xff1a; <template><el-switchinactive-text"否"active-text&quo…

【miniQMT实盘量化5】获取财务报表数据

前言 上面文章&#xff0c;我们介绍了如何获取实时数据&#xff0c;这篇文章&#xff0c;我们继续往下探讨&#xff0c;介绍关于财务报表数据的获取。 财务报表数据 财务报表数据&#xff0c;也就是常说的基本面数据&#xff0c;是除了行情数据之外&#xff0c;辅助我们投资…

PMP 考试的含金量怎么样?

这里可以三个思考题和三个价值点帮你认识PMP考试。 三个思维题 1.工作环境 PMP证书含金量的一个很大因素&#xff0c;就是考证的人是否对PMP证书有比较强的实际需求。相反&#xff0c;如果只是听别人说&#xff0c;PMP证书很好&#xff0c;不管工作中是否有需要&#xff0c;…

〖大前端 - 基础入门三大核心之JS篇㊷〗- DOM事件对象及它的属性

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…