Java实现Base64加解密方法汇总以及性能比较 有更新!

  |   0 评论   |   149 浏览

概述

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实现

这是最推荐的方式,无须导入第三库,性能也最好。

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编码过的字节数组字符
    }

commons.codec实现

commons.codec 图像文件与Base64字符串互转

先导库:

  • Maven方式
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>
  • Gradle方式
compile group: 'commons-codec', name: 'commons-codec', version: '1.10'

代码如下:

   //import org.apache.commons.codec.binary.Base64;
 
	public static String bytesToBase64(byte[] bytes) {
		return Base64.encodeBase64String(bytes);// 返回Base64编码过的字节数组字符串
	}

	/**
	 * 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
	 *
	 * @param path
	 *            图片路径
	 * @return base64字符串
	 */
	public static String imageToBase64(String path) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
		byte[] data = null;
		// 读取图片字节数组
		InputStream in = null;
		try {
			in = new FileInputStream(path);
			data = new byte[in.available()];
			in.read(data);
		} catch (IOException e) {
			e.fillInStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return Base64.encodeBase64String(data);// 返回Base64编码过的字节数组字符串
	}

	/**
	 * 处理Base64解码并写图片到指定位置
	 *
	 * @param base64
	 *            图片Base64数据
	 * @param path
	 *            图片保存路径
	 * @return
	 */
	public static boolean base64ToImageFile(String base64, String path) {// 对字符串进行Base64解码并生成图片
		// 生成jpeg图片
		try {
			OutputStream out = new FileOutputStream(path);
			return base64ToImageOutput(base64, out);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.fillInStackTrace();
		}
		return false;
	}

	/**
	 * 处理Base64解码并输出流
	 *
	 * @param base64
	 * @param out
	 * @return
	 */
	public static boolean base64ToImageOutput(String base64, OutputStream out)
			throws IOException {
		if (base64 == null) { // 图像数据为空
			return false;
		}
		try {
			// Base64解码
			byte[] bytes = org.apache.commons.codec.binary.Base64
					.decodeBase64(base64);
			for (int i = 0; i < bytes.length; ++i) {
				if (bytes[i] < 0) {// 调整异常数据
					bytes[i] += 256;
				}
			}
			// 生成jpeg图片
			out.write(bytes);
			out.flush();
			return true;
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

参考文献

评论

发表评论

validate