Base64编码的原理与常用实现
这篇主要是为了后面好介绍加密算法,做的铺垫。
这个是基础,什么是一个程序员的涵养,这些基础就是涵养。
平时可能用不到,但必须得会。
如果连这个原理都说不上来,就别玩王者荣耀绝地求生英雄联盟和平精英了,该好好补补了。
Base64编码定义
Base64编码是基于64个字符的编码方式。
所有的二进制数据都可以用这64个编码来表示。
怎么编码,64个字符有哪些,是基于一个规范的:RFC2045
Base64编码特点
Base64编码是可逆的。
编码后的结果,没有任何可读性。
适用性广泛,任何能转成二进制数的数据都能Base64编码。
Base64编码原理
Base64编码入参是二进制数
首先有个编码对照表,索引从0到63总共64个,对应着(A-Z)加(a-z)加(0-9)加(+)加(/)刚好64个字符。
编码有以下几步:
1、将数据拆成若干组,每组3个字节,即24位。
2、每组数据24位进行重组,分为4部分,那么每部分就是6位。
3、将每部分的高位补两个0,那么每部分都成8位了,即一个字节。此时这个组总共就是4个字节。
4、将每个字节的值换成10进制,由于高两位都是0,所以该字节的十进制数,最大就是63,最小是0,正好和上面的64个编码表的索引对上,然后得到对应字符。合起来就是最终编码的值。
如果数据的总字节数,不是3的倍数,那么就存在最后一组不够3个字节。这种情况,就还是按照上面的编码规则继续编(字节换成位,每6位高位补两个0变成一个字节)
情况1:
最后一组只有两个字节,那就是16位,
前6位,高位补两个0 ,变成一个字节,对照表拿到对应的第一个字符;
中间6位,高位补两个0 ,变成一个字节,对照表拿到对应的第二个字符;
后4位,高位补4个0,变成一个字节,对照表拿到对应的第三个字符;
第四个字符默认用=代替。
情况2
最后一组只有一个字节,那就是8位,
前6位,高位补两个0 ,变成一个字节,对照表拿到对应的第一个字符;
后2位,高位补6个0,变成一个字节,对照表拿到对应的第二个字符;
第三个字符和第四个字符默认都用=代替。
这也就是为什么,有时候看到的编码结果,结尾会有=或者==,就是这种不够的情况。
另外,每76个字符加一个换行符,这个是规定。
解码就反过来操作,是不是很简单。不考虑性能的话,完全可以自己尝试写一个Base64编码工具类玩玩。
Base64衍生编码方式
Base 16
Base 32
Url Base64
看过Base64的原理,Base16和Base32的就类似了,都是拆字节,然后高位补0,使得新的字节,最大是16或者32,然后照着表找对应字符。
url Base64的出现,是因为标准的Base64,最后两个字符+/在url中不能作为参数,所以url Base64主要改动就是把这两个字符换成了-和_。
Base64编码常见实现
Base64的实现有很多种,常见的两个:JDK的和Apache的
JDK的Base64
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
public class Base64Test {
public static void main(String[] args) throws IOException {
String str = "hello word";
BASE64Encoder base64Encoder = new BASE64Encoder();
// JDK Base64加密
String encode = base64Encoder.encode(str.getBytes());
System.out.println(encode);
BASE64Decoder base64Decoder = new BASE64Decoder();
// JDK Base64解密
byte[] bytes = base64Decoder.decodeBuffer(encode);
String res = new String(bytes);
System.out.println(res);
}
}
Apache的Base64
引入pom依赖:
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
import org.apache.commons.codec.binary.Base64;
public class ApacheBase64Test {
public static void main(String[] args) {
String str = "hello word";
// Apache Base64加密
byte[] encodeBytes = Base64.encodeBase64(str.getBytes());
System.out.println(new String(encodeBytes));
// Apache Base64解密
byte[] decodeBytes = Base64.decodeBase64(encodeBytes);
System.out.println(new String(decodeBytes));
}
}
当然,上面两个的结果都是:
aGVsbG8gd29yZA==
hello word
上一篇: Base64编码原理解析与Java实现