PKI - 电子邮件传输算法 - Base64 - 二进制的可视化展示
1. 定义
Base64是一种基于64个字符的编码算法,根据RFC2045的定义:“Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别(The Base64 ContentTransfer Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable)”。经过Base64编码后的数据会比原始数据略长,为原来的4/3倍。经Base64编码后的字符串的字符数是以4为单位的整数倍。
2. 实现原理
Base64算法主要是对给定的字符以与字符编码(如ASCII码,UTF8码)对应的十进制数为基准,做编码操作:
1)将给定的字符串以字符为单位转换为对应的字符编码(如ASCII码)。
2)将获得的字符编码转换为二进制码。
3)对获得的二进制码做分组转换操作,每3个8位二进制码为一组,转换为每4个6位二进制码为一组(不足6位时低位补0)。这是一个分组变化的过程,3个8位二进制码和4个6位二进制码的长度都是24位(3×8=4×6=24)。
4)对获得的4个6位二进制码补位,向6位二进制码添加2位高位0,组成4个8位二进制码。
5)将获得的4个8位二进制码转换为十进制码。
6)将获得的十进制码转换为Base64字符表中对应的字符。
2.1 ASCII码字符编码
字符 A
ASCII码 65
二进制码 01000001
4-6二进制码 010000 010000
4-8二进制码 00010000 00010000
十进制码 16 16
字符表映射码 Q Q = =
2.2 非ASCII码字符编码
字符 密
UTF-8码 -27 -81 -122
二级制码 11100101 10101111 10000110
4-6二级制码 111001 011010 111110 000110
4-8二进制码 00111001 00011010 00111110 00000110
十进制码 57 26 62 6
字符表映射码 5 a + G
3. 算法实现
3.1 Bouncy Castle
3.1.1 Maven Configuration
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.66</version>
</dependency>
3.1.2 Sample Code
org.bouncycastle.util.encoders.Base64
public String base64BcEncode(String data) throws UnsupportedEncodingException {
final byte[] encode = Base64.encode(data.getBytes("UTF-8"));
return new String(encode, "UTF-8");
}
public String base64BcDecode(String data) throws UnsupportedEncodingException {
final byte[] decode = Base64.decode(data.getBytes("UTF-8"));
return new String(decode, "UTF-8");
}
@Test
public void base64BcTest() throws UnsupportedEncodingException {
String data = "我是阿汤哥";
final String encoded = base64BcEncode(data);
System.out.println(data + " after base64 encode : " + encoded);
final String decoded = base64BcDecode(encoded);
System.out.println(encoded + " after base64 decode : " + decoded);
}
运行结果
我是阿汤哥 after base64 encode : 5oiR5piv6Zi/5rGk5ZOl
5oiR5piv6Zi/5rGk5ZOl after base64 decode : 我是阿汤哥
3.2 Commons Codec
3.3.1 Maven Configuration
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
3.3.2 Sample Code
org.apache.commons.codec.binary.Base64
encodeBase64方法支持参数isChunked设置,如果设置isChunked = true,则经过base64编码的结果会分成大小76字符的字符块,以换行分隔。
public String base64CodecEncode(String data) throws UnsupportedEncodingException {
final byte[] encode = Base64.encodeBase64(data.getBytes("UTF-8"), true);
return new String(encode, "UTF-8");
}
public String base64CodecDecode(String data) throws UnsupportedEncodingException {
final byte[] decode = Base64.decodeBase64(data.getBytes("UTF-8"));
return new String(decode, "UTF-8");
}
@Test
public void base64BcTest() throws UnsupportedEncodingException {
String data = "我是阿汤哥";
final String encoded = base64CodecEncode(data);
System.out.println(data + " after base64 encode : " + encoded);
final String decoded = base64CodecDecode(encoded);
System.out.println(encoded + " after base64 decode : " + decoded);
}
执行结果
我是阿汤哥 after base64 encode : 5oiR5piv6Zi/5rGk5ZOl
5oiR5piv6Zi/5rGk5ZOl
after base64 decode : 我是阿汤哥
3.3 Java 8
Java8默认提供Base64编解码支持。java.util.Base64。
3.3.1 Sample Code
public String base64Jdk8Encode(String data) throws UnsupportedEncodingException {
final byte[] encode = Base64.getEncoder().encode(data.getBytes("UTF-8"));
return new String(encode, "UTF-8");
}
public String base64Jdk8Decode(String data) throws UnsupportedEncodingException {
final byte[] decode = Base64.getDecoder().decode(data.getBytes("UTF-8"));
return new String(decode, "UTF-8");
}
@Test
public void base64BcTest() throws UnsupportedEncodingException {
String data = "我是阿汤哥";
final String encoded = base64Jdk8Encode(data);
System.out.println(data + " after base64 encode : " + encoded);
final String decoded = base64Jdk8Decode(encoded);
System.out.println(encoded + " after base64 decode : " + decoded);
}
执行结果
我是阿汤哥 after base64 encode : 5oiR5piv6Zi/5rGk5ZOl
5oiR5piv6Zi/5rGk5ZOl after base64 decode : 我是阿汤哥
参考
Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
梁栋. Java加密与解密的艺术(第2版). 机械工业出版社. Kindle 版本.