一、题目要求:
用Java实现一个文件批量加密解密工具,实现以下功能:
1. 要有图形界面。
2. 能够通过界面设置一个目录,软件对该目录下的所有文件进行加密或解密(使用对称或非对称加密算法)。
加密后删除原文件并保留加密后的文件,对加密后的文件进行解密后,删除加密后的文件,保留解密出的原文件。
3. 加密和解密时,如何选择密钥?
选定一张图片,求出它的MD5值,并用该值生成加密密钥。
4. 写一个验证程序,该程序完成:
(1)对加密前的所有文件,逐一求出MD5值,并记录到文件A中;
(2)然后对所有文件先加密后解密;再用该验证程序逐一求出解密后文件的MD5值,并记录到文件B中;
(3)比较文件A和文件B的内容,相同则返回true,否则返回false。
二、题目解答程序源代码如下
主程序类:
package com.student.main;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.Key;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import com.student.utils.FileMd5Utils;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
/**
* 获取文件列表的过滤器
*
* @author myname
*/
public class EnDeFiles extends JFrame {
/**
*
*/
private static final long serialVersionUID = 4534371106024773867L;
private final class ExtNameFileFilter implements FileFilter {
private String extName; // 文件扩展名
public ExtNameFileFilter(String extName) {
this.extName = extName;// 保存文件扩展名
}
@Override
public boolean accept(File pathname) {
// 过滤文件扩展名
if (pathname.getName().toUpperCase()
.endsWith(extName.toUpperCase()))
return true;
return false;
}
}
private JPanel contentPane;
private JTextField forderField;
private JTextField templetField;
private File dir;
private JTable table;
private JTextField extNameField;
private JSpinner startSpinner;
private File md5file1;
private File md5file2;
private String md5Origin;
/**
* Launch the application.主函数
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
EnDeFiles frame = new EnDeFiles(); // 创建窗体
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public EnDeFiles() {
setResizable(false);
setTitle("文件批量加密解密");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 383, 409);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout(); // 创建布局
gbl_contentPane.columnWidths = new int[] { 72, 54, 60, 87, 91, 0 }; // 列宽
gbl_contentPane.rowHeights = new int[] { 25, 25, 10, 25, 24, 25, 2, // 高
216, 0 };
gbl_contentPane.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, // 列权重
Double.MIN_VALUE };
gbl_contentPane.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, // 行权重
0.0, 0.0, 0.0, Double.MIN_VALUE };
contentPane.setLayout(gbl_contentPane); // 设定布局
JLabel label = new JLabel();
label.setText("文件加密解密:");
GridBagConstraints gbc_label = new GridBagConstraints();
gbc_label.fill = GridBagConstraints.VERTICAL;
gbc_label.insets = new Insets(0, 0, 5, 5);
gbc_label.gridwidth = 3;
gbc_label.gridx = 1;
gbc_label.gridy = 0;
contentPane.add(label, gbc_label);
JLabel label_1 = new JLabel();
label_1.setText("文件路径:");
GridBagConstraints gbc_label_1 = new GridBagConstraints();
gbc_label_1.anchor = GridBagConstraints.EAST;
gbc_label_1.fill = GridBagConstraints.VERTICAL;
gbc_label_1.insets = new Insets(0, 0, 5, 5);
gbc_label_1.gridx = 0;
gbc_label_1.gridy = 1;
contentPane.add(label_1, gbc_label_1);
forderField = new JTextField();
forderField.setText("");
GridBagConstraints gbc_forderField = new GridBagConstraints();
gbc_forderField.fill = GridBagConstraints.HORIZONTAL;
gbc_forderField.insets = new Insets(0, 0, 5, 5);
gbc_forderField.gridwidth = 3;
gbc_forderField.gridx = 1;
gbc_forderField.gridy = 1;
contentPane.add(forderField, gbc_forderField);
// ----------------选取目录,浏览目录下文件------------------
JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
do_button_actionPerformed(e);
}
});
button.setText("浏览");
GridBagConstraints gbc_button = new GridBagConstraints();
gbc_button.anchor = GridBagConstraints.NORTHWEST;
gbc_button.insets = new Insets(0, 0, 5, 0);
gbc_button.gridx = 4;
gbc_button.gridy = 1;
contentPane.add(button, gbc_button);
JSeparator separator_1 = new JSeparator();
GridBagConstraints gbc_separator_1 = new GridBagConstraints();
gbc_separator_1.fill = GridBagConstraints.BOTH;
gbc_separator_1.insets = new Insets(0, 0, 5, 0);
gbc_separator_1.gridwidth = 5;
gbc_separator_1.gridx = 0;
gbc_separator_1.gridy = 2;
contentPane.add(separator_1, gbc_separator_1);
// JLabel label_5 = new JLabel();
// label_5.setText("使用#可以指定数字计数所占的位置,使用*可以插入原文件名:");
// GridBagConstraints gbc_label_5 = new GridBagConstraints();
// gbc_label_5.fill = GridBagConstraints.VERTICAL;
// gbc_label_5.insets = new Insets(0, 0, 5, 0);
// gbc_label_5.gridwidth = 5;
// gbc_label_5.gridx = 0;
// gbc_label_5.gridy = 3;
// contentPane.add(label_5, gbc_label_5);
// JLabel label_2 = new JLabel();
// label_2.setText(" 扩展名:");
// GridBagConstraints gbc_label_2 = new GridBagConstraints();
// gbc_label_2.fill = GridBagConstraints.HORIZONTAL;
// gbc_label_2.insets = new Insets(0, 0, 5, 5);
// gbc_label_2.gridx = 2;
// gbc_label_2.gridy = 5;
// contentPane.add(label_2, gbc_label_2);
// 创建开始加密按钮---------------------------------
JButton startEncryptButton = new JButton();
startEncryptButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
do_startEncryptButton_actionPerformed(e);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
// 创建开始解密按钮---------------------------------
JButton startDecryptButton = new JButton();
startDecryptButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
do_startDecryptButton_actionPerformed(e);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
// extNameField = new JTextField();
// extNameField.setText("jpg");
// GridBagConstraints gbc_extNameField = new GridBagConstraints();
// gbc_extNameField.fill = GridBagConstraints.HORIZONTAL;
// gbc_extNameField.insets = new Insets(0, 0, 5, 5);
// gbc_extNameField.gridx = 3;
// gbc_extNameField.gridy = 5;
// contentPane.add(extNameField, gbc_extNameField);
startEncryptButton.setText("开始加密");
GridBagConstraints gbc_startButton = new GridBagConstraints();
gbc_startButton.anchor = GridBagConstraints.NORTH;
gbc_startButton.insets = new Insets(0, 0, 5, 0);
gbc_startButton.gridx = 0;
gbc_startButton.gridy = 5;
contentPane.add(startEncryptButton, gbc_startButton);
startDecryptButton.setText("开始解密");
GridBagConstraints gbc_startDeButton = new GridBagConstraints();
gbc_startDeButton.fill = GridBagConstraints.HORIZONTAL;
gbc_startDeButton.insets = new Insets(0, 0, 5, 0);
gbc_startDeButton.gridx = 4;
gbc_startDeButton.gridy = 5;
contentPane.add(startDecryptButton, gbc_startDeButton);
// contentPane.add(startDecryptButton);
JSeparator separator_2 = new JSeparator();
GridBagConstraints gbc_separator_2 = new GridBagConstraints();
gbc_separator_2.anchor = GridBagConstraints.NORTH;
gbc_separator_2.fill = GridBagConstraints.HORIZONTAL;
gbc_separator_2.insets = new Insets(0, 0, 5, 0);
gbc_separator_2.gridwidth = 5;
gbc_separator_2.gridx = 0;
gbc_separator_2.gridy = 6;
contentPane.add(separator_2, gbc_separator_2);
JScrollPane scrollPane = new JScrollPane();
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
gbc_scrollPane.fill = GridBagConstraints.BOTH;
gbc_scrollPane.gridwidth = 5;
gbc_scrollPane.gridx = 0;
gbc_scrollPane.gridy = 7;
contentPane.add(scrollPane, gbc_scrollPane);
table = new JTable();
table.setModel(new DefaultTableModel(new Object[][] {}, new String[] {
"旧文件名", "新文件名" }));
scrollPane.setViewportView(table);
}
/**
* 浏览按钮的事件处理方法
*
* @param e
*/
protected void do_button_actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();// 创建文件选择器
// 设置只选择文件夹
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int option = chooser.showOpenDialog(this);// 显示打开对话框
if (option == JFileChooser.APPROVE_OPTION) {
dir = chooser.getSelectedFile();// 获取选择的文件夹
} else {
dir = null;
}
forderField.setText(dir + "");// 显示文件夹信息
}
/**
* 开始按钮的事件处理方法
*
* @param e
*/
protected void do_startButton_actionPerformed(ActionEvent e) {
}
protected void do_startEncryptButton_actionPerformed(ActionEvent e)
throws Exception {
// 获取表格数据模型
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);// 清除表格数据
// 获取文件中文件列表数组
File[] files = dir.listFiles();
md5file1 = new File("D:/md5Origin.txt");
PrintStream ps = new PrintStream(new FileOutputStream(md5file1));
for (File file : files) {// 变量文件数组
// System.out.println("文件名: " + file.getName());
String filename = file.getName().substring(0,
file.getName().lastIndexOf("."));
String extname = file.getName().substring(
file.getName().lastIndexOf("."));
String enFilename = "en" + filename + extname;
// System.out.println("加密后的文件名: " + enFilename);
String path = file.getPath();
// System.out.println("全名: " + path);
String purePath = path.substring(0, path.lastIndexOf("\\") + 1);
// System.out.println("路径名:" + purePath);
// 使用图片生成密钥
String keyFileName = "G:/key.png";
String md5KeyStr = FileMd5Utils.getFileMD5String(keyFileName);
Key key = FileMd5Utils.getKey(md5KeyStr);
// 原文件md5值
md5Origin = FileMd5Utils.getFileMD5String(path);
// 写入文件md5文件中
// ps.append("\n");
ps.append(md5Origin);
// 加密文件
FileMd5Utils.encrypt(path, purePath + enFilename, key);
String name = purePath + enFilename;
// System.out.println(name);
// 把文件的旧名称与新名称添加到表格的数据模型
model.addRow(new String[] { file.getName(), name });
// 删除原文件
if (file.exists()) {
// System.gc();
boolean flag = file.delete();
// System.out.println(flag);
System.gc();
String filepath = file.getPath();
Runtime rt = Runtime.getRuntime();
try {
rt.exec("cmd /c del " + filepath);
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
System.out.println("文件不存在!");
}
}
}
protected void do_startDecryptButton_actionPerformed(ActionEvent e)
throws Exception {
// 获取表格数据模型
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);// 清除表格数据
// 获取文件中文件列表数组
File[] files = dir.listFiles();
md5file2 = new File("D:/md5Origin2.txt");
PrintStream ps = new PrintStream(new FileOutputStream(md5file2));
for (File file : files) {// 变量文件数组
// System.out.println("文件名: " + file.getName());
String filename = file.getName().substring(0,
file.getName().lastIndexOf("."));
String extname = file.getName().substring(
file.getName().lastIndexOf("."));
// String enFilename = "en" + filename + extname;
String deFilename = "de" + filename + extname;
// System.out.println("加密并解密后的文件名: " + deFilename);
String path = file.getPath();
// System.out.println("全名: " + path);
String purePath = path.substring(0, path.lastIndexOf("\\") + 1);
// System.out.println("路径名:" + purePath);
// 使用图片生成密钥
String keyFileName = "G:/key.png";
String md5KeyStr = FileMd5Utils.getFileMD5String(keyFileName);
Key key = FileMd5Utils.getKey(md5KeyStr);
// 解密文件
FileMd5Utils.decrypt(path, purePath + deFilename, key);
// 解密后文件md5值
String md5After = FileMd5Utils.getFileMD5String(purePath
+ deFilename);
// 写入文件md5文件中
ps.append(md5After);
// 比较前后的MD5是否一致
if(md5Origin.equals(md5After)){
System.out.println("前后MD5值一致,解密成功!");
}
String name = purePath + deFilename;
// System.out.println(name);
// 把文件的旧名称与新名称添加到表格的数据模型
model.addRow(new String[] { file.getName(), name });
if (file.exists()) {
file.delete();
}
}
}
}
工具类:
package com.student.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
public class FileMd5Utils {
protected static char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
protected static MessageDigest messageDigest = null;
static{
try{
messageDigest = MessageDigest.getInstance("MD5");
}catch (NoSuchAlgorithmException e) {
System.err.println(FileMd5Utils.class.getName()+"初始化失败,MessageDigest不支持MD5Util.");
e.printStackTrace();
}
}
/**
* 计算文件的MD5
* @param fileName 文件的绝对路径
* @return
* @throws IOException
*/
public static String getFileMD5String(String fileName) throws IOException{
File f = new File(fileName);
return getFileMD5String(f);
}
/**
* 计算文件的MD5,重载方法
* @param file 文件对象
* @return
* @throws IOException
*/
public static String getFileMD5String(File file) throws IOException{
FileInputStream in = new FileInputStream(file);
FileChannel ch = in.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
messageDigest.update(byteBuffer);
return bufferToHex(messageDigest.digest());
}
private static String bufferToHex(byte bytes[]) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte bytes[], int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
appendHexPair(bytes[l], stringbuffer);
}
return stringbuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
char c0 = hexDigits[(bt & 0xf0) >> 4];
char c1 = hexDigits[bt & 0xf];
stringbuffer.append(c0);
stringbuffer.append(c1);
}
public static Key getKey(String strKey){
try {
KeyGenerator _generator = KeyGenerator.getInstance("DES");
_generator.init(new SecureRandom(strKey.getBytes()));
Key key = _generator.generateKey();
_generator = null;
return key;
} catch (Exception e) {
throw new RuntimeException("Error initializing SqlMap class. Cause: " + e);
}
}
public static void encrypt(String file, String destFile, Key key) throws Exception {
Cipher cipher = Cipher.getInstance("DES");
// cipher.init(Cipher.ENCRYPT_MODE, getKey());
cipher.init(Cipher.ENCRYPT_MODE, key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(destFile);
CipherInputStream cis = new CipherInputStream(is, cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = cis.read(buffer)) > 0) {
out.write(buffer, 0, r);
}
cis.close();
is.close();
out.close();
}
public static void decrypt(String file, String dest, Key key) throws Exception {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(dest);
CipherOutputStream cos = new CipherOutputStream(out, cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = is.read(buffer)) >= 0) {
System.out.println();
cos.write(buffer, 0, r);
}
cos.close();
out.close();
is.close();
}
public static void main(String[] args) throws Exception {
String fileName = "G:/key.png";
String md5KeyStr = getFileMD5String(fileName);
Key key = getKey(md5KeyStr);
String md5Origin = getFileMD5String("G:/myworks/winter.doc");
encrypt("G:/myworks/winter.doc","G:/myworks/winterEncrypt.doc",key);
decrypt("G:/myworks/winterEncrypt.doc","G:/myworks/winterDec.doc",key);
String md5After = getFileMD5String("G:/myworks/winterDec.doc");
System.out.println(md5Origin.equals(md5After));
}
}