JAVA 实现磁盘文件加解密操作的示例代码

作者:Nemo 时间:2023-11-15 00:13:06 

简单实现了下:


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.*;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;

/**
* 文件/目录加解密相关
* @author: Nemo
* @date: 2019/3/19.
*/
public class FileCrote {

/**
  * 加密后的文件后缀
  */
 private static final String SUBFIX = ".enc";

/**
  * 执行路径
  */
 private static String path = "";

/**
  * 执行模式 1加密 2解密
  */
 private static String mode = "1";

/**
  * 执行密码
  */
 private static String pass = "";

private static String currentFilePath = null;

/**
  * 根据路径加密文件
  * 1、如果是目录,则找它下面的文件进行加密
  * 2、如果是文件,则直接加密
  * @param path
  * @throws IOException
  */
 private static void encrypt(String path) throws IOException, GeneralSecurityException {
   System.out.println("开始处理"+path);
   File file = new File(path);
   if(!file.exists()){
     System.out.println("需加密的路径不存在:"+path);
     return;
   }
   if(file.isDirectory()){
     //目录则遍历其下的文件
     File[] files = file.listFiles();
     if(files == null){
       return;
     }
     for (File subFile : files) {
       encrypt(subFile.getAbsolutePath());
     }
   }else{
     //文件则直接加密
     encrypt(file);
   }
 }

/**
  * 文件加密
  * @param file
  * @throws IOException
  */
 private static void encrypt(File file) throws IOException, GeneralSecurityException {
   String path = file.getAbsolutePath();
   if(path.endsWith(SUBFIX)){
     System.out.println("已加密文件不需再次加密"+path);
     return;
   }

String encFilePath = path + SUBFIX;
   File encFile = new File(encFilePath);

System.out.println("开始加密文件"+path);
   encryptFile(file,encFile,Cipher.ENCRYPT_MODE);
 }

/**
  * 加解密文件操作
  * @param srcFile
  * @param encFile
  * @throws IOException
  */
 private static void encryptFile(File srcFile, File encFile,int mode) throws IOException, GeneralSecurityException {
   if(!srcFile.exists()){
     System.out.println("source file not exixt");
     return;
   }

currentFilePath = srcFile.getAbsolutePath();

//密码
   Cipher cipher = getCipher(mode);

FileInputStream fis = null;
   FileOutputStream fos = null;
   try {
     fis = new FileInputStream(srcFile);
     fos = new FileOutputStream(encFile);

//真正处理
     crypt(fis, fos, cipher);
   } catch (IOException e) {
     e.printStackTrace();
   } finally {
     if (fis != null) {
       fis.close();
     }
     if (fos != null) {
       fos.close();
     }
   }

//源文件删除
   srcFile.delete();
 }

/**
  * 得到加解密Cipher
  * @param mode
  * @return
  * @throws GeneralSecurityException
  */
 private static Cipher getCipher(int mode) throws GeneralSecurityException {
   String type = "AES";
   Cipher cipher = Cipher.getInstance(type+"/ECB/PKCS5Padding");
   KeyGenerator kgen = KeyGenerator.getInstance(type);
   kgen.init(128, new SecureRandom(pass.getBytes()));
   SecretKey key = kgen.generateKey();
   cipher.init(mode,key);
   return cipher;
 }

/**
  * 加密解密流
  * @param in    加密解密前的流
  * @param out    加密解密后的流
  * @param cipher  加密解密
  * @throws IOException
  * @throws GeneralSecurityException
  */
 private static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException {
   int blockSize = cipher.getBlockSize() * 1000;
   int outputSize = cipher.getOutputSize(blockSize);

byte[] inBytes = new byte[blockSize];
   byte[] outBytes = new byte[outputSize];

int inLength = 0;
   boolean more = true;
   while (more) {
     inLength = in.read(inBytes);
     if (inLength == blockSize) {
       int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
       out.write(outBytes, 0, outLength);
     } else {
       more = false;
     }
   }
   if (inLength > 0) {
     outBytes = cipher.doFinal(inBytes, 0, inLength);
   } else {
     outBytes = cipher.doFinal();
   }
   out.write(outBytes);
 }

/**
  * 根据路径解密
  * 1、如果是目录,则找它下面的加密文件进行解密
  * 2、如果是文件,并且它是加密文件,则直接解密
  * @param path
  * @throws IOException
  */
 private static void decrypt(String path) throws IOException, GeneralSecurityException {
   System.out.println("开始处理"+path);
   File file = new File(path);
   if(!file.exists()){
     System.out.println("需解密的路径不存在:"+path);
     return;
   }
   if(file.isDirectory()){
     //目录则遍历其下的文件
     File[] files = file.listFiles();
     if(files == null){
       return;
     }
     for (File subFile : files) {
       decrypt(subFile.getAbsolutePath());
     }
   }else{
     decrypt(file);
   }
 }

/**
  * 文件解密
  * @param file
  * @throws IOException
  */
 private static void decrypt(File file) throws IOException, GeneralSecurityException {
   String path = file.getAbsolutePath();
   if(!path.endsWith(SUBFIX)){
     System.out.println("非加密文件不需解密"+path);
     return;
   }
   System.out.println("开始解密文件"+path);

String newPath = path.substring(0,path.length() - SUBFIX.length());
   encryptFile(file,new File(newPath),Cipher.DECRYPT_MODE);
 }

/**
  * 字符串是否非空
  * @param s
  * @return
  */
 private static boolean isNotEmpty(String s){
   if (s == null || "".equals(s)) {
     return false;
   }
   return true;
 }

/**
  * 开始处理
  * @throws IOException
  * @throws GeneralSecurityException
  */
 private static void deal() throws IOException, GeneralSecurityException {
   while (true) {
     print();
     BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
     String s = reader.readLine();
     if("path".equals(s)) {
       System.out.println("\r\n请输入执行路径\r\n");
       while (true) {
         reader = new BufferedReader(new InputStreamReader(System.in));
         s = reader.readLine();
         if (!isNotEmpty(s)) {
           System.out.println("\r\n请输入执行路径\r\n");
           continue;
         }else {
           File file = new File(s);
           if(!file.exists()){
             System.out.println("\r\n该路径不存在,请重新输入\r\n");
             continue;
           }
         }
         path = s;
         break;
       }
     } else if("pass".equals(s)) {
       System.out.println("\r\n请输入加/解密密码\r\n");
       while (true) {
         reader = new BufferedReader(new InputStreamReader(System.in));
         s = reader.readLine();
         if (!isNotEmpty(s)) {
           System.out.println("\r\n请输入加/解密密码\r\n");
           continue;
         }
         pass = s;
         break;
       }
     } else if ("1".equals(s)) {
       mode = s;
       System.out.println("\r\n当前已选模式:加密\n");
     } else if ("2".equals(s)) {
       mode = s;
       System.out.println("\r\n当前已选模式:解密\r\n");
     }else if("start".equals(s)){
       if(!isNotEmpty(path)) {
         System.out.println("\r\n请输入加/解密密码再开始\r\n");
         continue;
       }

if(!isNotEmpty(pass)) {
         System.out.println("\r\n请输入执行路径后再开始\r\n");
         continue;
       }

if ("1".equals(mode)) {
         encrypt(path);
         System.out.println("\r\n\r\n操作完成\r\n\r\n");
       } else {
         try {
           decrypt(path);
           System.out.println("\r\n\r\n操作完成\r\n\r\n");
         }catch (BadPaddingException e) {
           System.out.println("文件:"+currentFilePath+"解密失败,密码错误");
         }
       }
     }else if("quit".equals(s)){
       System.exit(-1);
     } else {
       System.out.println("\r\n输入错误\r\n");
     }
   }
 }

/**
  * 输出提示语
  */
 private static void print(){
   System.out.println("\r\n" +
       "输入path开始选择执行路径\r\n" +
       "输入pass开始选择加/解密密码\r\n" +
       "输入如下数字以选择处理模式:1 加密 2 解密\r\n" +
       "输入start则开始执行已选操作\r\n" +
       "输入quit则退出程序\r\n" +
       "当前选择路径:"+path+"\r\n" +
       "当前选择模式:"+mode+"\r\n" +
       "当前选择密码:"+pass+"\r\n");
 }

public static void main(String args[]) throws IOException, GeneralSecurityException {
   deal();
 }

}

来源:https://www.link-nemo.com/u/10001/post/80269

标签:Java,磁盘,加解密,文件
0
投稿

猜你喜欢

  • C#中加载dll并调用其函数的实现方法

    2022-06-27 17:14:08
  • 网易Java程序员两轮面试 请问你能答对几个?

    2023-11-29 10:32:08
  • 浅析c# 线程同步

    2022-09-19 18:43:03
  • Java实现验证码具体代码(图片、汉字)

    2023-03-25 11:14:31
  • android中sqlite的按条件查找的小例子

    2021-06-18 03:39:33
  • android 使用Xml文件定义Shape方式

    2022-09-08 19:19:38
  • java中不定长参数的实例用法

    2021-06-17 02:49:35
  • 关于自定义过滤器获取不到session问题

    2022-05-16 11:30:21
  • SpringBoot中定位切点的两种常用方法

    2023-09-26 08:45:17
  • SpringMVC实现数据绑定及表单标签

    2022-03-24 18:06:47
  • Android仿银行客户签名并且保存签名的截图文件并命名为本地时间

    2023-09-19 22:42:48
  • Android多线程+单线程+断点续传+进度条显示下载功能

    2023-08-13 15:48:26
  • Android studio点击跳转WebView详解

    2022-12-12 05:11:17
  • java实现打砖块小游戏

    2021-07-26 14:47:11
  • C#中委托、事件和回调的使用及说明

    2023-08-13 01:00:24
  • 结合mybatis-plus实现简单不需要写sql的多表查询

    2021-06-25 12:54:22
  • Android中ProgressDialog的dismiss()与cancel()方法的区别

    2021-07-27 04:14:24
  • c#典型工厂化实现实例

    2022-01-04 19:41:08
  • Android自定义View实现垂直时间轴布局

    2022-12-12 15:21:16
  • Android利用OpenGLES绘制天空盒实例教程

    2023-11-19 16:07:27
  • asp之家 软件编程 m.aspxhome.com