Java实现Base64加解密方法汇总以及性能比较
概述
BASE64 编码是一种常用的字符编码,在很多地方都会用到。但base64不是安全领域下的加密解密算法。能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使用ASCII字符。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据。
Base64 实现方式
Java实现Base64加解密的方式主要有以下几种:
1:JDK中的sun.misc套件
(在JDK1.6之前,JDK核心类一直没有Base64的实现类,有人建议用Sun/Oracle JDK里面的sun.misc.BASE64Encoder 和 sun.misc.BASE64Decoder,使用它们的优点就是不需要依赖第三方类库,缺点就是可能在未来版本会被删除(用maven编译会发出警告),而且性能不佳,后面会有性能测试。)
2:第三方扩展包 bouncy castle
3:第三方扩展包 commons codec
4:JDK8及更高版本中的 java.util.Base64
(推荐
:在Java 8在java.util包下面实现了BASE64编解码API,而且性能不俗,API也简单易懂)
5:JDK6中的DatatypeConverter
(JDK1.6中添加了另一个Base64的实现,javax.xml.bind.DatatypeConverter两个静态方法parseBase64Binary 和 printBase64Binary,隐藏在javax.xml.bind包下面,不被很多开发者知道。)
6:第三方实现Base64的API Google Guava库
第二个便是Google Guava库里面的com.google.common.io.BaseEncoding.base64() 这个静态方法;
7:第三方实现Base64的API net.iharder.Base64
第三个是net.iharder.Base64,这个jar包就一个类;
8:第三方实现Base64的API MigBase64
(最后一个,号称Base64编码速度最快的MigBase64,而且是10年前的实现,到现在是否能保持这个称号,测一测便知道;)
有关这几种实现方式的性能对比请看:http://www.importnew.com/14961.html
这里主要讲下第三种和第四种:
前面做人脸识别的时候,我自己搭建了一个websocket服务器,需要把图片文件转成base64字符串传给硬件,然后再从硬件设备取出白名单所有注册用户的列表信息。刚开始的时候不熟悉Base64加解密有三种BASE64编解码器方式。我用标准的BASE64编码(服务器)与MIME编码(设备)后的图片字符串对接的时候,发现了问题。
首先,图片文件经过标准BASE64编码和MIME编码后的字符串长得不一样。
其次,经过MIME编码后的字符串不能按照标准BASE64解码方式转成图片文件。
Base64三种编解码器
-
Basic编码
:是标准的BASE64编码,用于处理常规的需求 -
URL编码
:使用下划线替换URL里面的反斜线“/” -
MIME编码
:使用基本的字母数字产生BASE64输出,而且对MIME格式友好:每一行输出不超过76个字符,而且每行以“\r\n”符结束。
现在以JDK8 java.util.Base64
来说明:
Basic编码:是标准的BASE64编码,用于处理常规的需求
//编码
String asB64 = Base64.getEncoder().encodeToString("some string".getBytes("utf-8"));
System.out.println(asB64);// 输出为: c29tZSBzdHJpbmc=`
//解码
byte [] asBytes = Base64.getDecoder().decode("c29tZSBzdHJpbmc=");`
System.out.println(new String(asBytes,"utf-8"));// 输出为: some string`
URL编码:使用下划线替换URL里面的反斜线“/”
String urlEncoded = Base64.getUrlEncoder().encodeToString("subjects?abcd".getBytes("utf-8"));
System.out.println("Using URL Alphabet: "+ urlEncoded);
// 输出为:
Using URL Alphabet: c3ViamVjdHM_YWJjZA==
MIME编码:使用基本的字母数字产生BASE64输出,而且对MIME格式友好:每一行输出不超过76个字符,而且每行以“\r\n”符结束。
StringBuilder sb =new StringBuilder();
for(int t = 0; t <10; ++t) {
sb.append(UUID.randomUUID().toString());
}
byte [] toEncode = sb.toString().getBytes("utf-8");
String mimeEncoded = Base64.getMimeEncoder().encodeToString(toEncode);
System.out.println(mimeEncoded);
其中第三方扩展包 commons codec就是依据MIME编码器来进行编码操作的。可以看它提供的官方API:
http://commons.apache.org/proper/commons-codec/archives/1.10/apidocs/index.html
看到这里就恍然大悟了,现在用java.util.Base64 MIME方式来解码commons codec编码的Base64字符串,能顺利的解码成图片文件。
java.util.Base64 MIME方式来解码
//base64字符串转图像文件
public static boolean baseStrToImg(String baseStr, String imgFilePath) {
if (StringUtils.isBlank(baseStr)) {// 图像数据为空
return false;
}
try {
// Base64解码 关键采用MIME解码
byte[] bytes = Base64.getMimeDecoder().decode(baseStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(bytes);
out.flush();
out.close();
return true;
}
catch (Exception e) {
return false;
}
}
java.util.Base64 MIME方式来编码
//图像文件转base64字符串
public static String imgToBaseStr(String imgFilePath) {
InputStream in = null;
byte[] data = null;
// 读取图片字节数组
try {
in = new FileInputStream(imgFilePath);
data = new byte[in.available()];
in.read(data);
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
return Base64.getMimeEncoder().encodeToString(data); // 返回Base64编码过的字节数组字符
}
参考文献
- Java 8新特性探究(十一)Base64详解
- Java实现Base64加解密的方式
- RFC 2045中规定base64编码结果中一行的字符个数不能超过76个
- RFC 2045 英文:http://www.ietf.org/rfc/rfc2045.txt
原文地址:https://www.yundashi168.com/articles/2019/01/17/1547708559206.html