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
发布了203 篇原创文章 · 获赞 186 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/java_zhangshuai/article/details/105548280