本文链接:https://www.cnblogs.com/muphy/p/15142524.html
gitee:https://gitee.com/muphy1112/file-security
因为有些文件在网盘分享或下载会出现违规的情况,特意写了一个工具,不知道效果如何,上传之前需要先加密,下载后在解密
加密方式:
文件名采用简单的base64编码以尝试绕过检索,加密后文件格式为.azi
文件内容加密:读取每个字节根据配置的最简单的密钥加密
工具使用方法:
编译
javac FileSecurity.java --encoding UTF-8
加密
java FileSecurity filepath [-e] [secretKey] filepath: 文件或者目录绝对路径 -e: -e表示加密,-d表示解密,默认值:-e secretKey: 加密密钥,和-e连用,字节类型,取值范围:[-127~-1, 1~127],默认值:1
加密例子,加密后会生成“文件名对应关系.txt”文件
java FileSecurity ./ java FileSecurity D:/tmp/ -e java FileSecurity D:/tmp/ -e 23
解密
java FileSecurity filepath -d filepath: 文件或者目录绝对路径 -d: -e表示加密,-d表示解密,默认值:-e
解密例子,解密后也会生成“文件名对应关系.txt”文件
java FileSecurity D:/tmp/ -d
FileSecurity.java
import java.io.*; import java.util.Arrays; import java.util.Base64; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; /*** * 文件加解密 * * @author: 若非 * @date: 2021/8/15 3:29 */ public class FileConversion { private static ExecutorService executorService; private static byte secretKey = 1; private static boolean isEncrypt = true; private static String currentPath = "./"; private static AtomicLong count = new AtomicLong(0); private static final Base64.Decoder decoder = Base64.getDecoder(); private static final Base64.Encoder encoder = Base64.getEncoder(); private static FileWriter fileWriter; public static void main(String[] args) throws IOException { // System.out.println("VklQ56ysMTT-or77ogYrlpKnnmoTm/gJ3ot6/miJHlupT-or6XmgI7kuYjnkIbmuIXmpZrvvIgz77yJ".replace("-", "/")); if (args.length < 1) { usage(); return; } System.out.println("参数:" + Arrays.toString(args)); String filepath = args[0]; System.out.println("操作路径:" + filepath); if (args.length > 1) { isEncrypt = "-e".equals(args[1]); if (isEncrypt) { if (args.length > 2) { try { secretKey = Byte.parseByte(args[2]); if (secretKey == 0) { System.out.println("参数错误:加密密钥,字节类型,和-e连用,取值范围:[-127~-1, 1~127],当前值:" + args[2]); usage(); return; } } catch (NumberFormatException e) { System.out.println("参数错误:加密密钥,字节类型,和-e连用,取值范围:[-127~-1, 1~127],当前值:" + args[2]); usage(); return; } } System.out.println("密钥:" + secretKey); } else { if (!"-d".equals(args[1])) { System.out.println("参数错误,无法确认加解密类型,当前值:" + args[1]); usage(); return; } } } executorService = Executors.newFixedThreadPool(5); convert(filepath); while (true) { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } if (count.get() <= 0) { executorService.shutdown(); break; } } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } executorService.shutdownNow(); fileWriter.close(); System.out.println("完成!"); } private static void usage() { System.out.println("usage:"); System.out.println("java -jar file-conversion.jar filepath [-e | -d] [secretKey]"); System.out.println("\tfilepath:\t文件或者目录绝对路径"); System.out.println("\t[-e | -d]:\t-e表示加密,-d表示解密,默认值:-e"); System.out.println("\tsecretKey:\t加密密钥,和-e连用,字节类型,取值范围:[-127~-1, 1~127],默认值:1"); } public static void convert(String filename) throws IOException { if (filename == null || filename.isEmpty()) { System.out.println("文件或者目录不存在,文件名:" + filename); return; } File file = new File(filename); if (file == null || !file.exists()) { System.out.println("文件或者目录不存在,文件名:" + file); return; } if (file.isFile()) { currentPath = file.getParentFile().getCanonicalPath(); } else if (file.isDirectory()) { currentPath = file.getCanonicalPath(); } File dir = new File(currentPath); if (!dir.exists()) { dir.mkdirs(); } fileWriter = new FileWriter(currentPath + File.separatorChar + "文件名对应关系.txt", true); if (isEncrypt) { currentPath = currentPath + File.separatorChar + "encrypt"; } else { currentPath = currentPath + File.separatorChar + "decrypt"; } fileWriter.write("输出路径:" + currentPath + "\r\n"); fileWriter.flush(); convert(file, ""); } public static void convert(final File file, final String path) throws IOException { if (file.isFile()) { executorService.submit(new Runnable() { @Override public void run() { count.incrementAndGet(); try { doConvert(file, path); } catch (IOException e) { e.printStackTrace(); } finally { count.decrementAndGet(); } } }); return; } if (file.isDirectory() && file.canRead()) { for (File f : file.listFiles()) { if (f.isDirectory()) { convert(f, path + File.separatorChar + f.getName()); } else { convert(f, path); } } } } private static void doConvert(File file, String path) throws IOException { // String filename = file.getCanonicalPath(); if (file.getCanonicalPath().contains(currentPath)) { return; } String outFilepath; if (isEncrypt) { outFilepath = getEncryptPath(file.getName(), path); } else { outFilepath = getDecryptPath(file.getName(), path); } if (outFilepath == null) { return; } File outFile = new File(outFilepath); File parentFile = outFile.getParentFile(); synchronized (fileWriter) { if (path.length() > 1) { fileWriter.write(path + File.separatorChar + file.getName() + "--->" + path + File.separatorChar + outFile.getName()); } else { fileWriter.write(file.getName() + " ---> " + outFile.getName()); } fileWriter.write("\r\n"); fileWriter.flush(); } if (!parentFile.exists()) { parentFile.mkdirs(); } byte key = secretKey; FileOutputStream fos = new FileOutputStream(outFile); FileInputStream fis = new FileInputStream(file); byte[] buf = new byte[1024]; int length; //循环读取文件内容,输入流中将最多buf.length个字节的数据读入一个buf数组中,返回类型是读取到的字节数。 //当文件读取到结尾时返回 -1,循环结束。 if (isEncrypt) { fos.write(‘a‘); fos.write(‘z‘); fos.write(‘i‘); fos.write(key); } else { if (fis.read() != ‘a‘ || fis.read() != ‘z‘ || fis.read() != ‘i‘) { System.out.println("解密文件不是azi文件,不能解密,文件名:" + file.getCanonicalPath()); return; } key = (byte) fis.read(); } while ((length = fis.read(buf)) != -1) { for (int i = 0; i < length; i++) { if (isEncrypt) { buf[i] += key; } else { buf[i] -= key; } } fos.write(buf, 0, length); //System.out.print(new String(buf,0,length)); } //最后记得,关闭流 fis.close(); fos.close(); } private static String getDecryptPath(String filename, String path) throws IOException { String outFilename = new String(decoder.decode(filename.replaceAll("\\.[aA][zZ][iI]$", "")), "UTF-8").replace("-", "/"); File outFile = new File(currentPath + path + File.separatorChar + outFilename); if (outFile.exists()) { System.out.println("解密输出文件已经存在,文件名:" + outFile.getCanonicalPath()); return null; } System.out.println("解密文件:" + filename + "--->" + outFilename); return outFile.getCanonicalPath(); } private static String getEncryptPath(String filename, String path) throws IOException { String outFilename = encoder.encodeToString(filename.getBytes("UTF-8")).replace("/", "-") + ".azi"; File outFile = new File(currentPath + path + File.separatorChar + outFilename); if (outFile.exists()) { System.out.println("加密输出文件已经存在,文件名:" + outFile.getCanonicalPath()); return null; } System.out.println("加密文件:" + filename + "--->" + outFilename); return outFile.getCanonicalPath(); } }
原文:https://www.cnblogs.com/muphy/p/15142524.html