【密码学】仿凯撒密码对文件加密(适用于World、Excel、PDF、txt、SQL等场景)


前言

文档显示乱码相信大家一定不陌生,一份很喜欢的文档内容/数据,下载到自己电脑上却是这样的

在这里插入图片描述
项目中一些核心程序打开是这样的
在这里插入图片描述
文件加密,不仅可以提高数据安全性,还可以在很大程度上保护个人权益/财产不被侵犯。
本篇文章采用的是对称加密方式,效果如下。
在这里插入图片描述


一、密码学入门

常见的加密方式分为两种,对称加密和非对称加密。

1.对称加密

对称加密简单来说就是两个相同的钥匙开同一把锁

它符合大多数人的思维逻辑,就好比你们家钥匙可以在门内外实现上锁开锁操作。缺点就是解密是加密的逆过程,知道加密规则立马可以获得解密规则,安全性较低。

对称加密最早使用是在公元前54年,古罗马军事统帅凯撒大帝发明的凯撒密码,在战争中把写在长布条上的情报系在信使的腰上进行传递。
在这里插入图片描述
只有将该布条缠在特定粗细的木棒中,横向观看才能看到传递的真正信息,单截获一个布条很难获取到上面的信息。

在信息传递落后的时代中由于凯撒密码的使用,使得凯撒大帝在战争中占据了先发优势,并赢得了多次胜利。
在这里插入图片描述
但是由于凯撒加密规则过于简单,它仅采用位移加密方式,只对26个字母进行位移替换加密,破译相对简单,最多尝试25次即可破解内容。

即便如此,在一战和二战中对称加密仍然应用非常广泛,编译员使用英文字母,阿拉伯数字,符号进行对称加密。但加密原理不变,破译只需花费更多时间。
在这里插入图片描述
这也就解释了为什么在谍战片中总能看到一群人在不停的计算所有的可能性,利用归纳出的各字符频率来还原密钥
在这里插入图片描述

2.非对称加密

非对称加密简单来说就是两个不同的钥匙开同一把锁

非对称加密分为公钥和私钥,接发双方各有一个私钥,公钥公开运输。甲将消息“我爱你”利用公钥加密,并附属私钥A加密过的签名运输到乙,乙接到消息用私钥B解密并确认签名正确后则成功接收。
在这里插入图片描述
总结:
1.发送者只需要知道加密密钥;
2.接收者只需要知道解密密钥
3.解密密钥不可以被窃听者获取
4.加密密钥被窃听者获取也不影响信息安全
在这里插入图片描述

通俗来说,对于对称加密方式,直接用密钥传输,破译者更易抢夺密钥,通过暴力破解来获取信息;

而对于非对称加密方式,破译者不易抢夺私钥,并且获取单向私钥无法解开密文,通常采用截取公钥并替换内容,伪装成发送方对接收方进行信息篡改和窃取来达到己方利益。因此,对于公钥信息的可靠性问题,研究人员提出了私钥数字签名的方式来解决信息传递安全。
生活中最典型的例子就是,淘宝买家和卖家依靠阿里巴巴中间过渡来进行可靠交流。

二、程序代码

在project中,将下面四个类放入一个包下即可

1.Index类

首页设计
设置三个按钮:加密、解密、九芒星;
设置六个监听:加密×2、解密×2、九芒星×2
设置四个方法:初始化、组件设计、添加元素、监听
在这里插入图片描述

package 九芒星加密;

import javax.swing.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

public class Index extends JFrame {
	private static final int WIDTH = 600;
    private static final int HEIGHT = 400;
    private JPanel mainPanel = new JPanel();
    private JButton encryptBtn = new JButton("加密");
    private JButton decryptBtn = new JButton("解密");
    private JButton myself = new JButton("CSDN——九芒星#");
    private JPanel p = new JPanel();
	private JFrame f1;
	public Index(String title){
        super(title);
        this.init();
    }
    //初始化
    public void init(){
    	p.add(myself);
    	mainPanel.add(p);
        this.setPanelFont();
        this.addElements();
        this.addListener();
        this.setFramePosition();       
    }    
    
    //设置组件
    public void setPanelFont(){
        int btnWidth = WIDTH/2 - 20;
        int btnHeight = HEIGHT - 80;
        mainPanel.setLayout(null);
        //加密按钮
        encryptBtn.setBackground(Color.green);
        encryptBtn.setFont(new Font("黑体",Font.BOLD,50));
        encryptBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));//手状光标
        encryptBtn.setBounds(10,10,btnWidth,btnHeight);//组件位置
        //解密按钮
        decryptBtn.setBackground(Color.CYAN);
        decryptBtn.setFont(new Font("黑体",Font.BOLD,50));
        decryptBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        decryptBtn.setBounds(btnWidth+20,10,btnWidth,btnHeight);
        //九芒星#
        //myself.setBackground(Color.CYAN);
        myself.setFont(new Font("黑体",Font.BOLD,20));
        //myself.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        myself.setBounds(100,335,400,25);

    }
    //添加元素
    public void addElements(){
        mainPanel.add(encryptBtn);
        mainPanel.add(decryptBtn);
        mainPanel.add(myself);
        this.add(mainPanel);
    }
    
    //监听
    public void addListener(){ 	
    	//加密
    	//鼠标事件监听器
        encryptBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
                Index.this.setVisible(false);
                new MajorFR("九芒星_文件加密","加密").init();//加密初始化
            }

            @Override
            public void mouseExited(MouseEvent e) {//鼠标离开(加密组件区域)
                encryptBtn.setFont(new Font("黑体",Font.BOLD,50));
                encryptBtn.setForeground(Color.BLACK);
            }
        });
        //鼠标运动监听器
        encryptBtn.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {//鼠标移动(加密组件区域)
                encryptBtn.setFont(new Font("黑体",Font.BOLD,60));
                encryptBtn.setForeground(Color.RED);//组件区域内保持红色
            }
        });
        
        //解密
        //鼠标事件监听器
        decryptBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
                Index.this.setVisible(false);
                new MajorFR("九芒星_文件解密","解密").init();
            }

            @Override
            public void mouseExited(MouseEvent e) {//鼠标离开
                decryptBtn.setFont(new Font("黑体",Font.BOLD,50));
                decryptBtn.setForeground(Color.BLACK);
            }
        });
        //鼠标运动监听器
        decryptBtn.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {//鼠标移动
                decryptBtn.setFont(new Font("黑体",Font.BOLD,60));
                decryptBtn.setForeground(Color.RED);//组件范围内保持绿色
            }
        });
        //九芒星#
        myself.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
                Index.this.setVisible(false);
                new MajorFR("九芒星_文件解密","CSDN——九芒星#").init();
            }

            @Override
            public void mouseExited(MouseEvent e) {//鼠标离开
                decryptBtn.setFont(new Font("黑体",Font.BOLD,10));
                decryptBtn.setForeground(Color.BLACK);
            }
        });
        myself.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				f1 = Object.getInstance();				
				f1.setTitle("九芒星#");
				f1.setSize(500, 500);
				f1.setLocation(700, 335);
				f1.setVisible(true);	
			}
		});
    }
   
    public static class Object extends JFrame{
		/**
		 * 在静态内部类中定义单例对象
		 */
		public static class SingletonClass1{
			private static final Object instance = new Object();
			
		}
		private Object(){
			
		}
		public static Object getInstance(){
			return SingletonClass1.instance;
		}
	}
       
    //窗口位置
    private void setFramePosition() {
        //获得当前屏幕的长宽
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = (int)screenSize.getWidth();
        int screenHeight = (int)screenSize.getHeight();
        //组件位置
        this.setBounds(screenWidth/2-WIDTH/2,screenHeight/2-HEIGHT/2,WIDTH,HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭
        this.setResizable(false);
        this.setVisible(true);
    }

}


2.MajorFR类

分页设计
设置三个编辑文本组件:文件路经×2、输入密码;
设置三个监听对象:路经选择按钮×2、开始加密按钮、输入密码;
设置五个标签:源路经提示、目的路经提示、勾选密码提示、输入密码提示、开始加密提示;
设置五个方法:窗体初始化、监听、添加组件、组件布局、窗体布局
设置七个按钮:文件路经选择×2、勾选密码×3、开始加密×2;
在这里插入图片描述

package 九芒星加密;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

public class MajorFR extends JFrame{
	private static final int WIDTH = 600;
    private static final int HEIGHT = 400;
    private String option;
    private JFileChooser fileSelect;

    private JLabel sourceVersion;
    private JTextField sourceText;
    private JButton sourceButton;

    private JLabel aimVersion;
    private JTextField aimText;
    private JButton aimButton;

    private JLabel selectPasswordText;
    private JCheckBox selectPassword;
    private JTextField inPassword;

    private JButton start;

    private JPanel panel1;
    private JPanel panel2;
    private JPanel panel3;
    private JPanel panel4;
    private JFrame f1;

    public MajorFR(String tile,String option){
        super(tile);
        this.option = option;
    }
    //分页部件初始化
    private void initComponent(){
    	//源地址
        fileSelect = new JFileChooser("C:\\");
        
        sourceVersion = new JLabel("请选择待"+option+"的文件/文件夹:");//标签
        sourceText = new JTextField(20);//文本输入
        sourceButton = new JButton("···");//选择按钮
        //目的地址
        aimVersion = new JLabel("请选择"+option+"后文件的存放路径:");//标签
        aimText = new JTextField(20);//文本输入
        aimButton = new JButton("···");//选择按钮
        //选择密码
        if (option.equals("加密")){
            selectPasswordText = new JLabel("使用密码"+option);
        }else if (option.equals("解密")){
            selectPasswordText = new JLabel("该文件有密码");
        }
        if (option.equals("CSDN——九芒星#")){
            System.out.println("点击成功");
        }
        //重置密码
        selectPassword = new JCheckBox();
        inPassword = new JTextField(20);
        //开始加密/解密
        start = new JButton("开始"+this.option);
        start.setEnabled(false);
        //初始化四个面板
        panel1 = new JPanel();
        panel2 = new JPanel();
        panel3 = new JPanel();
        panel4 = new JPanel();
    }
    //初始化
    public void init(){
        this.initComponent();//分页部件
        this.setPanelFont();//首页组件
        this.addElements();//元素
        this.addListener();//监听
        this.setFramePosition();//窗口
    }
    //监听
    private void addListener() {
    	//鼠标监听_源地址按钮
        sourceButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
                fileSelect.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);//选择文件或者文件夹
                fileSelect.showDialog(panel1, "请选择要"+option+"的文件/文件夹");
                File file = fileSelect.getSelectedFile();
                if(file!=null)
                    sourceText.setText(file.getAbsolutePath());//源地址绝对路经
            }
        });
        //鼠标监听_目的地址按钮
        aimButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
                fileSelect.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//只能选目录,不能选单个文件
                fileSelect.showDialog(panel2,"请选择"+option+"后文件的存放路径");
                File file = fileSelect.getSelectedFile();
                if(file!=null) {
                	//从0开始索引到最后一个空字符串停止
                    String sourceParent = sourceText.getText().substring(0, sourceText.getText().lastIndexOf("\\"));
//                    System.out.println(sourceParent);
                    aimText.setText(file.getAbsolutePath());//目的地址绝对路经
//                    System.out.println("--");
                    if(aimText.getText().equals(sourceText.getText())){//原路径不能等于目的路经
                        JOptionPane.showMessageDialog(MajorFR.this,"文件路径选择不合法,请重新选择!");
                        start.setEnabled(false);
                    }else {
                        start.setEnabled(true);
                    }
                }
            }
        });
        //鼠标监听_开始加密按钮
        start.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {//鼠标点击
            	//源地址空/源地址文本为空格(空字符串)/目的地址空/目的地址文本为空格(空字符串)
            	//trim:去掉字符串开头和结尾所有空格并返回字符串
                if(sourceText.getText()==null || sourceText.getText().trim().equals("") || aimText.getText()==null || aimText.getText().trim().equals("")) {
                    //提示错误
                	JOptionPane.showMessageDialog(MajorFR.this, "您还没有选择文件呢,请选择您的文件");
                    return;
                }
                //地址赋值
                String sourcePath = sourceText.getText();
                String objPath = aimText.getText();
                boolean isEncryp = false;
                if (option.equals("加密")){
                    isEncryp = true;
                }else if(option.equals("解密")){
                    isEncryp = false;
                }else{
                    JOptionPane.showMessageDialog(MajorFR.this,"程序错误,请重启");
                }
                
                try {
                    FileAction fileSuperOption = new FileAction();//new一个对象,保证每次的isFirstCopy刚开始都是true!!
                    if (inPassword.getText()==null || inPassword.getText().equals("")) {
                        //不使用密码加密/解密
                        fileSuperOption.superCopy(sourcePath, objPath, isEncryp);
                    }
                    else {
                        //使用密码加密/解密
                        fileSuperOption.superCopy(sourcePath, objPath, isEncryp, inPassword.getText());
                    }
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(MajorFR.this,"路径有误,建议不要手工输入!");
                }
                //JOptionPane.showMessageDialog(CoreFrame.this,option+"成功!");
                int item = JOptionPane.showConfirmDialog(MajorFR.this, option + "成功!是否返回功能首页?");
                if (item==0){
                    MajorFR.this.setVisible(false);//隐藏当前窗体
                    new Index("九芒星_文件加密/解密工具");
                }
            }
        });
        //动作监听器
        selectPassword.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {//事件监听
                if (selectPassword.isSelected()){//是否选中密码按钮组件
                    String password = JOptionPane.showInputDialog(MajorFR.this, "请输入密码:");
                    if (password==null ||password.equals("")){
                        selectPassword.setSelected(false);
                    }
                    inPassword.setText(password);
//                    System.out.println(inPassword.getText());
                }else {
                    inPassword.setText("");
//                    System.out.println(inPassword.getText());
                }
            }
        });
    }

    //添加组件
    private void addElements() {
        panel1.add(sourceVersion);//源地址标签面板
        panel1.add(sourceText);//源地址文本框面板
        panel1.add(sourceButton);//源地址按钮面板
        panel2.add(aimVersion);//目的地址标签面板
        panel2.add(aimText);//目的地址文本框面板
        panel2.add(aimButton);//目的地址按钮面板
        panel3.add(selectPassword);//选中密码按钮面板
        panel3.add(selectPasswordText);//选中密码文本面板
        panel3.add(inPassword);//输入密码面板
        panel4.add(start);//开始加(解)密按钮面板

        this.add(panel1);
        this.add(panel2);
        this.add(panel3);
        this.add(panel4);
    }
    //首页组件
    private void setPanelFont() {
        this.setLayout(null);//绝对布局
        this.panel1.setBounds(20,20,500,50);
        this.panel2.setBounds(20,120,500,50);
        this.panel3.setBounds(20,220,500,50);
        this.inPassword.setVisible(false);
        this.panel4.setBounds(20,300,500,50);
    }

    private void setFramePosition() {
        //获得当前屏幕的长宽
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int screenWidth = (int)screenSize.getWidth();
        int screenHeight = (int)screenSize.getHeight();
        //组件位置
        this.setBounds(screenWidth/2-WIDTH/2,screenHeight/2-HEIGHT/2,WIDTH,HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.setVisible(true);
    }

}

3.FileAction类

设置加密解密算法,对文件,密码进行两次加密,提高安全性。加密算法为对称加密,自动加索引并首尾调换实现乱码操作。

package 九芒星加密;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.ImageIcon;

public class FileAction {
    private boolean isFirstCopy = true;
    private boolean goThrough = false;
    private String password = null;
    public void superCopy(String path,String objPath,boolean opFlag,String ...passArgs){
        if (passArgs.length==1){
            goThrough = true;
            password = passArgs[0];
        }
        File file = new File(path);
        String historyFileName = file.getName();
        //首次操作且文件名为1
        if(isFirstCopy && file.isFile()){
        	//获取前缀
            String prefix = historyFileName.substring(0, historyFileName.lastIndexOf("."));
            //获取后缀
            String suffix = historyFileName.substring(historyFileName.lastIndexOf("."));
            //加密
            if (opFlag)
                if (historyFileName.contains("解密版"))
                    historyFileName = historyFileName.replace("解密版","加密版");
                else
                    historyFileName = prefix.concat("(加密版)").concat(suffix);
            //解密
            if (!opFlag)
                if (historyFileName.contains("加密版"))
                    historyFileName = historyFileName.replace("加密版","解密版");
                else
                    historyFileName = prefix.concat("(解密版)").concat(suffix);
            isFirstCopy = false;
        }
        //首次操作且路经为1
        if(isFirstCopy && file.isDirectory()){
            if (opFlag) {
                if (historyFileName.contains("解密版"))
                    historyFileName = historyFileName.replace("解密版","加密版");
                else
                    historyFileName = historyFileName.concat("(加密版)");
            }
            if (!opFlag)
                if (historyFileName.contains("加密版"))
                    historyFileName = historyFileName.replace("加密版","解密版");
                else
                    historyFileName = historyFileName.concat("(解密版)");
            isFirstCopy = false;
        }
        String newFilePath = objPath+"\\"+historyFileName;
        File objFile = new File(newFilePath);
        File[] lists = file.listFiles();
        //若list没有地址,在堆内不存在
        if (lists!=null){
            //说明它是一个文件夹
            objFile.mkdir();//在目标路径创建好空的文件夹
            //若堆内有list且不为空
            if (lists.length!=0){
            	//遍历list地址
                for(File f:lists){
                    superCopy(f.getAbsolutePath(),objFile.getAbsolutePath(),opFlag);
                }
            }
        //list在堆内存在,说明它是一个文件
        }else{
        	//节点流(直接作用于文件)
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                fis = new FileInputStream(file);
                fos = new FileOutputStream(objFile);
                byte[] bytes = new byte[1024];
                int count = fis.read(bytes);
                //文件流对文件夹进行递归
                while (count!=-1){//递归整个文件夹
                	//加密
                    if (opFlag){
                        if (count==bytes.length){
                            if(goThrough)
                                fos.write(FileAction.encryptionByPass(bytes,password));//密码加密
                            else
                                fos.write(FileAction.encryption(bytes));//普通加密
                        }else {
                        	//拷贝文件
                            byte[] b = new byte[count];
                            for (int i = 0;i<b.length;i++){
                                b[i] = bytes[i];
                            }
                            if(goThrough)
                                fos.write(FileAction.encryptionByPass(b,password));
                            else
                                fos.write(FileAction.encryption(b));
                        }
                    //解密
                    }else {
                        if (count==bytes.length){
                            if(goThrough)
                                fos.write(FileAction.decryptionByPass(bytes,password));
                            else
                                fos.write(FileAction.decryption(bytes));
                        }else {
                        	//还原文件
                            byte[] b = new byte[count];
                            for (int i = 0;i<b.length;i++){
                                b[i] = bytes[i];
                            }
                            if(goThrough)
                                fos.write(FileAction.decryptionByPass(b,password));
                            else
                                fos.write(FileAction.decryption(b));
                        }
                    }
                    fos.flush();//清空缓冲区数据,保证缓冲清空输出
                    count = fis.read(bytes);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if (fis!=null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (fos!=null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //加密算法
    private static byte[] encryption(byte[] bytes){
    	//每一个字节的值,都加上它的索引号
        for (int i = 0;i<bytes.length;i++){
            bytes[i] = (byte)(bytes[i]+i);
        }
        //交换第一个字节和最后一个字节的位置
        byte temp = bytes[0];
        bytes[0] = bytes[bytes.length-1];
        bytes[bytes.length-1] = temp;
        return bytes;

    }
    //解密算法(加密的逆)
    private static byte[] decryption(byte[] bytes){
    	//字节首尾交换位置
        byte temp = bytes[0];
        bytes[0] = bytes[bytes.length-1];
        bytes[bytes.length-1] = temp;
        //每一个字节的值,都减去它的索引号
        for (int i = 0;i<bytes.length;i++){
            bytes[i] = (byte)(bytes[i]-i);
        }
        return bytes;
    }
    //密码加密算法
    public static byte[] encryptionByPass(byte[] bytes,String password){
        byte[] passBytes = encryptionPass(password);
        //每个字节对整体长度取模
        for(int i = 0;i<bytes.length;i++){
            bytes[i] = (byte)(bytes[i]+passBytes[i%passBytes.length]);
        }
        //字节首尾交换位置
        byte temp = bytes[0];
        bytes[0] = bytes[bytes.length-1];
        bytes[bytes.length-1] = temp;
        return bytes;         
    }
    //密码解密算法
    public static byte[] decryptionByPass(byte[] bytes,String password){
        byte[] passBytes = encryptionPass(password);
        //字节首尾交换位置
        byte temp = bytes[0];
        bytes[0] = bytes[bytes.length-1];
        bytes[bytes.length-1] = temp;
        //每个字节对整体长度取模
        for (int i = 0;i<bytes.length;i++){
            bytes[i] = (byte)(bytes[i]-passBytes[i%passBytes.length]);
        }
        return bytes;
    }
    //使用加密算法,对密码进行二次加密,提高安全性
    private static byte[] encryptionPass(String password){
        byte[] passBytes = password.getBytes();
        return encryption(encryption(passBytes));
    }
    
    public static void main(String[] args) {
        FileAction fso = new FileAction();
        String historyFile = "F:\\第一层\\第二层(加密版)";
        String newFile = "F:\\第一层";
        String password = "123456";
        fso.superCopy(historyFile,newFile,false,password);//加密
    }
}


4.Test类

测试

package 九芒星加密;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class Test {
    public static void main(String[] args) {
    	new Index("九芒星_文件加密/解密工具");    	
    }
}

在这里插入图片描述

注:重要文件加密后记得保存密钥,以便自行解密

猜你喜欢

转载自blog.csdn.net/weixin_48701521/article/details/124163142