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

1131704-c4a6d12bb6250665.png

看到这里就恍然大悟了,现在用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编码过的字节数组字符
    }

参考文献

原文地址:https://www.yundashi168.com/articles/2019/01/17/1547708559206.html

猜你喜欢

转载自blog.csdn.net/weixin_34130269/article/details/87019882