一、题目要求:
用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)); } }