0%

文件编解码及加密读写

前言

简单了解对文本内容或二级制的内容,进行加密解密(也可以理解为编解码)操作。

Base64 编解码

base64 并不该算作一种加密方式,更倾向于他是一种编码方式,将二进制文件进行编码后,方便传输,同时编码后的内容可以进行反编码,恢复内容。

  • base64 文本编解码
1
2
3
4
5
6
7
8
9
10
11
import org.apache.commons.codec.binary.Base64;

private static void basic() {
String chinese = "中华人民共和国";
System.out.println("origin is " + chinese);
String encode = Base64.encodeBase64String(chinese.getBytes());
System.out.println("encode --> " + encode);
byte[] temp = Base64.decodeBase64(encode);
String decode = new String(temp);
System.out.println("decode --> " + decode);
}

可以非常方便的使用 apache commons-codec 库中的 Base64 工具类进行关于 base64 的编解码工作。

  • base64 图片编码

比如在 Web 端常用的图片 base64 编码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static String imageToBase64(String path) {
String prefix = processPrefix(path);
String result = "";
InputStream input;
byte[] data = {};
try {
input = new FileInputStream(path);
data = new byte[input.available()];
input.read(data);
input.close();
} catch (IOException e) {
e.printStackTrace();
}
result = Base64.encodeBase64String(data);
return prefix + result;
}

以上便是把图片转换为 String 的 base64 实现,最终结果是类似 “data:image/filetype,xyz” 这样的数据。
这里需要注意的是不同类型的图片(文件),这里 image/filetype 中 filetype 顾名思义是文件类型,因此在转换时需要做特殊处理。

自定义加密/解密

通过以上实现,我们可以了解到,对文件进行编解码就是对文件中对应的输入内容进行一些算法操作,这样的算法操作有不同的目的,有的可能只是想获取文件的唯一标识,比如 MD5 等。有的是为了对输入内容进行一些[干扰],使得常规的解码方式,无法识别对这些进行过干扰的内容,从而实现所谓的加密。这里就来尝试一下对文件的加密操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
*
* @param filepath 要加密文件的路劲
* @param outputPath 加密文件的输出路径
* @param encrypt 是否加密,true 加密,false 解密
* @return 是否成功
*/
public static boolean encryptFile(String filepath, String outputPath,boolean encrypt) {
boolean result = false;
File file = new File(filepath);
File outputFile = new File(outputPath);
outputFile.deleteOnExit();
try {
FileInputStream fileInputStream = new FileInputStream(file);
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);

BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

int n;
while ((n = bufferedInputStream.read()) != -1) {
// 加密/解密算法
encrypt(bufferedOutputStream,n,encrypt);
}
bufferedInputStream.close();
bufferedOutputStream.close();
result = true;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}

回归到本质,对文件进行加密/解密,其实就是文件内容通过自定义的方式添加和移除一些干扰项。比如上面的实现,encrypt 操作如果简单的实现为 bufferedOutputStream.write(n); 那么这个过程其实就是一个简单的文件复制操作而已,因此关于文件加解密的重点就是如何实现 encryt 方法。

1
2
3
4
5
6
7
private static void encrypt(BufferedOutputStream bos, int length, boolean encode) throws IOException {
if (encode) {
bos.write(length - 10);
} else {
bos.write(length + 10);
}
}

可以看到,这里的加密操作还是非常简单的,就是在加密时对输出流的写操作偏移了 10 个长度,对应的解密操作,在对加密过后文件,进行恢复的时候,要进行相应的反向操作。

测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
private static final String INPUT_FILE = "./resources/poet.txt";
private static final String MIDDLE_FILE = "./resources/poet_secret.txt";
private static final String OUTPUT_FILE = "./resources/poet_rollback.txt";

public static void main(String[] args) {
try (MethodCost cost = new MethodCost()) {

boolean result = FileEncryptor.encryptFile(INPUT_FILE, MIDDLE_FILE, true);
System.out.println("result is " + result);
}
try (MethodCost cost = new MethodCost()) {

boolean result1 = FileEncryptor.encryptFile(MIDDLE_FILE, OUTPUT_FILE, false);
System.out.println("result1 is " + result1);
}
simpleTextTest();
}
}
  • output
1
2
3
4
result is true
method cost :3617700
result1 is true
method cost :1532200

从总体执行多次的结果来看,加密时间还是比解密长的。

再看一下最终输出的文件

  • 文件变化

    • poet.txt

      1
      2
      3
      先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
      。。。。。

    • poet_secret.txt

      1
      �{~ۮ��w�ޥ�岂�}�ڮ��y�ۅ��w��z�ܵv�vx  ڱ�۳�޵�ݜ�岂ڮ�ޗ�ܬ�ߑ�岂ڮ�ݕ��vޞ
    • poet_rollback.txt

      1
      2
      先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
      。。。。。

这里以《出师表》全文作为实例,可以看到加密之后,txt 文本再次打开已经完全变成了乱码,解码之后的文件又恢复到了最初的样子。

总结

文本或二级制文件加密、解密本质上其实都是一样的,都是回归到对编码的再次操作,不同的加密或解密方式,唯一的区别就是编码方式的实现不同而已。

加个鸡腿呗.