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 版本.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值