一、Base64简介
Base64是一种基于64个字符的编码算法,根据RFC 2045的定义:“Base64内容传送编码是以一种任意8位字节序列组合的描述形式,这种形式不易被人直接识别"。经过Base64编码后的数据会比原始数据略长,为原来的4/3倍。字符串的字符数是以4位单位的整数倍。
二、实现原理
- 将给定的字符串以字符为单位,转换为对应的字符编码(ASCII)
- 将获得的字符编码转换为二进制码
- 对获得的二进制编码做分组操作,每3个8位二进制码为一组,转换为每4个6位二进制码为一组(不足6位时低位补0)
- 对获得的4-6二进制码补位,向6位二进制码添加2位高位0,组成4个8位二进制码
- 将获得的4-8二进制码转换为十进制码
- 将获得的十进制码转换为Base64字符表中对应的字符
三、Base64字符映射表
在这里插入图片描述
1. ASCII码加密推导演示
字符 B ASCII码 66(不足24位) 二进制码 01000010 4-6二进制码 010000 100000 (不足低位补0) 4-8二进制码 00010000 00100000 (高位补0) 十进制码 16 32 字符表映射码 Q g = = (不足4个的补=)
2. UTF-8码介绍
UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。UTF-8最多可用到6个字节。
如表(补位): 1字节 0xxxxxxx 2字节 110xxxxx 10xxxxxx 3字节 1110xxxx 10xxxxxx 10xxxxxx 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
3. UTF-8加密推导演示
字符 爱 utf-8 %u7231 二进制转换 0111(7) 0010(2) 0011(3) 0001(1) //括号对应上面的utf-8码 二进制码 (1110)0111 (10)001000 (10)110001 //括号里为填充码 4-6二进制码 111001 111000 100010 110001 4-8二进制码 00111001 00111000 00100010 00110001 十进制码 57 56 34 49 字符映射码 5 4 i x
四、Base64算法两大实现比较
Bouncy Castle和Commons Codec两大开源组件提供了一般Base64算法的实现。
1. 区别:
- Bouncy Castle遵循的是一般Base64算法,也就是简单的根据字符映射表做了编码转换。
- Commons Codec遵循RFC 2045的相关定义,同时也支持一般Base64算法的实现。
- Commons Codec还提供了Base64算法的定制实现,可以自定义字符数和行末符号。
- Commons Codec还提供了输入输出流的实现
2. Bouncy Castle代码演示:
//jar包引入 <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.61</version> </dependency> //Castle工具类 import org.bouncycastle.util.encoders.Base64; public class CastlesUtil { //字符编码集 public static final String ENCODING = "UTF-8"; /** * 将字符串类型进行Base64编码 * @param data 明文 * @return 密文 * @throws Exception */ public static String encode(String data) throws Exception { //执行编码 byte[] bytes = Base64.encode(data.getBytes(ENCODING)); return new String(bytes,ENCODING); } /** * 解码 * @param data 密文 * @return 明文 * @throws Exception */ public static String decode(String data) throws Exception { //执行解码 byte[] bytes = Base64.decode(data); return new String(bytes,ENCODING); } } //单元测试 @Test public void test(){ try { //加密 String str = "梵如花"; System.out.println("原文:"+str); str = CastlesUtil.encode(str); System.out.println("密文:"+str); //解密 System.out.println("解密:"+CastlesUtil.decode(str)); } catch (Exception e) { e.printStackTrace(); } } //打印结果 原文:梵如花 密文:5qK15aaC6Iqx 解密:梵如花
3. Commons Codec代码演示:
//引入jar包 <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.12</version> </dependency> //Commons工具类 import org.apache.commons.codec.binary.Base64; public class CommonsUntils { //字符编码集 public static final String ENCODING = "UTF-8"; public static String encode(String data) throws Exception { //执行编码 byte[] bytes = Base64.encodeBase64(data.getBytes(ENCODING)); return new String(bytes,ENCODING); } public static String encodeSafe(String data) throws Exception { //执行编码 byte[] bytes = Base64.encodeBase64(data.getBytes(ENCODING),true); return new String(bytes,ENCODING); } public static String decode(String data) throws Exception { //执行解码 byte[] bytes = Base64.decodeBase64(data); return new String(bytes,ENCODING); } } //单元测试 @Test public void test(){ try { //加密 String str = "梵如花是一个好的县令,没有错的哈哈哈哈哈哈哈哈哈哈或或"; System.out.println("原文:"+str); str = CommonsUntils.encode(str); System.out.println("普通加密:"+str); str = "梵如花是一个好的县令,没有错的哈哈哈哈哈哈哈哈哈哈或或"; str = CommonsUntils.encodeSafe(str); System.out.println("安全加密:"+str); //解密 System.out.println("解密:"+CommonsUntils.decode(str)); } catch (Exception e) { e.printStackTrace(); } } //输出结果,注意的是,如果str比较短,则安全和非安全的输出结果是一致的 原文:梵如花是一个好的县令,没有错的哈哈哈哈哈哈哈哈哈哈或或 普通加密:5qK15aaC6Iqx5piv5LiA5Liq5aW955qE5Y6/5Luk77yM5rKh5pyJ6ZSZ55qE5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5oiW5oiW 安全加密:5qK15aaC6Iqx5piv5LiA5Liq5aW955qE5Y6/5Luk77yM5rKh5pyJ6ZSZ55qE5ZOI5ZOI5ZOI5ZOI 5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5oiW5oiW
五、Url Base64算法
Bouncy Castle遵从了RFC 4648的建议,使用"."做填充符,构建定长Url Base64编码;
Commons Codec舍弃了填充符,使用不定长Url Base64编码。
byte[] byts = Base64.encode("梵如花是一个好的县令,没有错的哈哈哈哈哈哈哈哈哈哈或或".getBytes("utf-8")); System.out.println("普通加密:"+new String(byts,"utf-8")); byte[] bytes = UrlBase64.encode("梵如花是一个好的县令,没有错的哈哈哈哈哈哈哈哈哈哈或或".getBytes("utf-8")); System.out.println("url:"+new String(bytes,"utf-8")); //打印结果: 普通加密:5qK15aaC6Iqx5piv5LiA5Liq5aW955qE5Y6/5Luk77yM5rKh5pyJ6ZSZ55qE5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5oiW5oiW url:5qK15aaC6Iqx5piv5LiA5Liq5aW955qE5Y6_5Luk77yM5rKh5pyJ6ZSZ55qE5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5ZOI5oiW5oiW
六、应用场景
Base64算法广泛应用于电子邮件传输,网络信息传输,以及密钥和证书文件的文本式保存。在数据保密要求强度不高的情况下,可以使用Base64算法做简单的数据加密。