hi,大家好,我是开发者FTD。置信很多同学在工作中,常常会用到Base64编码,那大家晓得为什么会有Base64编码吗?咱们为什么要应用它呢,它又是怎么实现的呢?上面就让咱们来一起深刻探索一下Base64编码吧。

Base 家族

在开始之前,咱们先给大家介绍一下Base家族。尽管咱们在工作中应用最多的是Base64,然而Base家族可不止是只有Base64,除了Base64之外,Base家族还有Base32和Base16。

咱们都晓得ASCII 编码,ASCII 编码是用256(2的8次方)个字符,对二进制数据进行编码的形式,同样的

  • Base64 编码是用64(2的6次方)个字符,对二进制数据进行编码的形式
  • Base32 编码是用32(2的5次方)个字符,对二进制数据进行编码的形式
  • Base16 编码是用16(2的4次方)个字符,对二进制数据进行编码的形式

那Base家族有这么多编码模式,为什么偏偏应用Base64呢?

  • Base64 编码是用64(2的6次方)个特定的ASCII字符来示意256(2的8次方)个ASCII字符,也就是说三个ASCII字符通过Base64编码后变为四个的ASCII字符显示(公约数为24),编码后数据长度比原来减少1/3,有余3n用“=”补足。
  • Base32 编码就是用32(2的5次方)个特定的ASCII字符来示意256(2的8次方)个ASCII码,也就是说五个ASCII字符通过Base32编码后会变为八个ASCII字符显示(公约数为40),编码后数据长度比原来减少3/5,有余8n用“=”补足。
  • Base16 编码就是用16(2的4次方)个特定的ASCII字符示意256(2的8次方)个ASCII字符,也就是说一个ASCII字符通过Base16编码后会变为两个ASCII字符显示,编码后数据长度比原来增加一倍,有余2n用“=”补足。

从下面能够看出Base64编码后,长度减少是起码的,这也是咱们选用Base64的一个重要起因。

Base64 简介

Base64顾名思义,就是基于64个可打印字符来示意二进制数据的一种办法,留神它并不是一种加密算法。对于64个打印字符,咱们只须要6个二进制位就能够齐全示意了。那么咱们如何利用8个二进制位来示意只须要6个二进制位就能够齐全示意的可打印字符呢?因为2的6次方等于64,所以咱们能够将每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节须要用4个可打印字符来示意。

Base64是从二进制数据到字符的过程。所以计算机中所有的内容,包含文本、图片、音频、视频等等都能够应用Base64编码来示意。

Base64 编码原理

Base64编码就是应用64个字符作为一个根本字符集:

小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)

而后,所有其余符号都依据肯定规定转换成这个字符集中的字符。

具体来说,Base64编码的转换形式能够分为以下四步:

  • 第一步,将每三个字节作为一组,一共是24个二进制位
  • 第二步,将这24个二进制位分为四组,每个组有6个二进制位
  • 第三步,在每组后面加两个00,扩大成32个二进制位,即四个字节
  • 第四步,依据下表,失去扩大后的每个字节的对应符号,这就是Base64的编码值

Base64 编码的字符索引表如下所示:

数值字符数值字符数值字符数值字符
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

有了这个字符索引表,咱们就能够把任意的二进制转换成Base64的编码了,上面咱们通过几个例子,给大家展现一下转换的过程。

1,假如当初有字符串 FTD 须要转换成base64的编码格局

  • 第一步:“F”、“T”、"D" 字符对应的ASCII码值别离为70,84,68,对应的二进制值是01000110、01010100、01000100。如图第二三行所示,由此组成一个24位的二进制字符串。
  • 第二步:将24位二进制依照每6位二进制位一组分成四组。
  • 第三步:在下面每一组后面补两个0,扩大成32个二进制位,此时变为四个字节:00010001、00100101、00010001、00000100。别离对应的值(Base64编码索引)为:17、37、17、4。
  • 第四步:用下面的值在Base64 字符索引表中进行查找,别离对应:R、I、R、E。

因而字符串 “FTD” 通过Base64 编码之后就变为:RIRE 。

2,下面的例子中的字符正好是三个字节,如果字节数有余三个时该如何解决呢?上面咱们以 FFT 别离举例说明如下:

如上表所示,因为字符F的二进制为01000110,依照每6位进行分组,此时只能分成一组,第二组短少4位,如果位数有余时,用0补齐;第三组和第四组齐全没有数据,则用=补上。因而,字符F通过Base64编码后失去的数值为Rg==

3,上面咱们再看一下如果只有两个字符的状况:

如上表所示,这个也属于位数有余,须要补位的状况。第一组和第二组依照失常的分组计算,第三组因为有余位数,最初两位补0,第四组齐全没有数据,用=补上。因而,字符FT通过Base64编码后失去的数值为RlQ=

对于中文的Base64编码

大家都晓得中文编码有很多种,例如GB2312、GBK、GB18030,不同的汉字应用不同的编码格局进行编码后,它的二进制是不同的,所以在进行Base64编码后,他们的Base64编码的值也是不同的。这就要求咱们在解码的时候须要留神原文的字符集格局,肯定要保持一致能力正确解码。

例如:

中文 “【我是开发者FTD】公众号” UTF-8 格局的Base64 编码后的值是:44CQ5oiR5piv5byA5Y+R6ICFRlRE44CR5YWs5LyX5Y+3

中文 “【我是开发者FTD】公众号” GB2312 格局的Base64 编码后的值是:ob7O0srHv6q3otXfRlREob+5q9bausU=

Base64 是加密算法吗?

Base64 次要不是用来加密的,它次要的用处是把一些二进制数转成一般字符用于网络传输,这是因为一些二进制字符在传输协定中属于控制字符,不能间接在网络上传输。另外,还有一些零碎中只能应用ASCII字符。Base64 编码就是用来将非ASCII字符的数据转换成ASCII字符的一种办法。Base64 并不是平安畛域下的加密解密算法,尽管有时候也会常常看到所谓的Base64加密解密算法。其实Base64只能算是一个编码算法,对数据内容进行编码来适宜网络传输。尽管Base64编码过后原文也变成无奈间接了解的字符格局,然而这种编码方式比拟高级,很简略,很容易就能够被还原成原文,所以如果有比拟重要的信息须要加密,肯定要应用咱们之前文章中介绍的那些加密算法进行数据的平安爱护。

Base64 编码实现

Java语言中有多个库实现了Base64编码,不论哪一个库,最终的后果都是一样的。

JDK 提供的 Base64 编码实现:

public static String encode(String data) {    return Base64.getEncoder().encodeToString(data.getBytes());}public static String decode(String base64Data) {    return new String(Base64.getDecoder().decode(base64Data));}

Bouncy Castle 提供的 Base64 编码实现:

public static String encode(String data) {    return new String(Base64.encode(data.getBytes()));}public static String decode(String base64Data) {    return new String(Base64.decode(base64Data));}

Commons Codec 提供的 Base64 编码实现:

public static String encode(String data) {    return Base64.encodeBase64String(data.getBytes());}public static String decode(String base64Data) {    return new String(Base64.decodeBase64(base64Data));}

上面让咱们用Java语言的实现来验证一下,咱们第二章节的推理是否正确吧,代码如下:

public static void main(String[] args) {    String ftd = "FTD";    String ft = "FT";    String f = "F";    System.out.println("FTD base64 编码:" + encode(ftd));    System.out.println("FT base64 编码:" + encode(ft));    System.out.println("F base64 编码:" + encode(f));}

输入后果为:

FTD base64 编码:RlREFT base64 编码:RlQ=F base64 编码:Rg==

能够看到,和咱们剖析所得的后果是齐全一样的。

查看残缺代码请拜访:

https://github.com/ForTheDevelopers/JavaSecurity

总结

Base64是咱们在工作中常常用到,然而很少有人会深入研究一下它的实现原理,如果了解不当,甚至可能还会有人用它当做加解密用到业务零碎要害地位,可能会引发比较严重的结果,置信大家看完上述的内容后,应该对Base64编码曾经有了粗浅的了解了吧。

技术人,技术魂,每天肝一篇技术文,ヾ(◍°∇°◍)ノ゙哈哈~

对于作者
  • GitHub:https://github.com/ForTheDevelopers
  • 掘金:https://juejin.cn/user/1204720472953022
  • CSDN:https://blog.csdn.net/ForTheDevelopers
  • 知乎:https://www.zhihu.com/people/forthedevelopers
  • segmentfault:https://segmentfault.com/u/for_the_developers
分割作者
  • 微信号:ForTheDeveloper
  • 公众号:ForTheDevelopers