一、介绍
Base64算法是一种基于64个字符的编码算法,仅是一种算法,并不是加密算法(因为算法是公开的)。
经过Base64编码后的数据会比原始数据略长,为原来的4/3倍。经过Base64编码后的字符串的字符数是以4为单位的整数倍。
Base64字符映射表
上图映射表中最后一个字符是等号,它是用来补位的。
Url Base64算法主要是替换了Base64字符映射表中的第62和63个字符,也就是将"+"和“/”符号替换为了"-"和“_”
二、实现原理
Base64算法主要是将给定的字符以与字符编码(ASCII码、UTF-8码)对应的十进制数为基准做编码操作:
(1)将给定的字符串以字符为单位,转为为对应的字符编码(如ASCII码)
(2)将获得的字符编码转换为二进制码
(3)对获得的二进制码做分组转换操作,每3个8位二进制码为一组,转换为4个6位二进制码为一组(不足6位时低位补0)。这是一个分组变化的过程,3个8位的二进制码和4个6位的二进制码的长度都是21位(3 x 8 = 4 x 6 = 24)
(4)对获得的4-6二进制码补位,向6位二进制码添加两位高位0,组成4个8位二进制码
(5)将获得4-8二进制码转换为十进制码
(6)将获得的十进制码转换为Base64字符表中对应的字符
例:对字符串“A”进行Base64编码
字符 A
ASCII码 65
二进制码 0100 0001
4-6二进制码 010000 010000
4-8二进制码 00010000 00010000
十进制码 16 16
字符表映射码 Q Q = =
字符串“A”经过Base64编码后得到“QQ==”这样的字符串
Base64编码后的字符串是以4个字符为单位,其长度只能是4个字符的整数倍。
示例:非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
字符串“密”经过Base64编码后得到的字符串是“5a+G”
三、实现示例
在JAVA API中sun公司没有提供相应BASE64编码的实现;Bouncy Castle和Commons Codec(apache提供)两大开源组织包,提供了算法的实现
Bouncy Castle实现
import org.bouncycastle.util.encoders.Base64;
/**
* Base64编码解码组件
*
* @author user
*/
public abstract class Base64Coder {
public final static String ENCODING = "UTF-8";
public static String encode(String data) throws Exception {
/* 执行编码 */
byte[] b = Base64.encode(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
public static String decode(String data) throws Exception {
/* 执行解码 */
byte[] b = Base64.decode(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
}
Commons Codec实现
import org.apache.commons.codec.binary.Base64;
public abstract class Base64Coder {
public final static String ENCODING = "UTF-8";
/**
* 一般Base64编码实现
*/
public static String encode(String data) throws Exception {
/* 执行编码 */
byte[] b = Base64.encodeBase64(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
/**
* 用于RFC 2045标准的Base64编码实现; RFC 2045定义:每行为76个字符,行末加入一个回车换行符('\r\n')
*/
public static String encodeSafe(String data) throws Exception {
byte[] b = Base64.encodeBase64(data.getBytes(ENCODING), true);
return new String(b, ENCODING);
}
public static String decode(String data) throws Exception {
/* 执行解码 */
byte[] b = Base64.decodeBase64(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
}
四、Url Base64
符号“+”和符号“/”不允许出现在URL中,RFC 4648中给出了相应的替代符号“-”和“_”。同样,符号“=”也不允许出现在URL中。
Bouncy Castle和Commons Codec都实现了Url Base64算法,不同的是Bouncy Castle使用“.”作为填充符,而Commons Codec直接放弃了填充符,使用不定长的Url Base64编码。
Bouncy Castle实现
import org.bouncycastle.util.encoders.UrlBase64;
/**
* URL Base64组件
*
* @author user
*/
public class UrlBase64Coder {
public static final String ENCODING = "UTF-8";
public static String encode(String data) throws Exception {
/* 执行编码 */
byte[] b = UrlBase64.encode(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
public static String decode(String data) throws Exception {
/* 执行解码 */
byte[] b = UrlBase64.decode(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
}
public class UrlBase64CoderTest {
@Test
public final void test() throws Exception {
String inputStr = "Java加密与解密艺术";
System.err.println("原文:\t" + inputStr);
/* 进行UrlBase64编码 */
String code = UrlBase64Coder.encode(inputStr);
System.err.println("编码后:\t" + code);
/* 进行UrlBase64解码 */
String outputStr = UrlBase64Coder.decode(code);
System.err.println("解码后:\t" + outputStr);
/* 验证UrlBase64编码解码一致性 */
Assert.assertEquals(inputStr, outputStr);
}
}
输出:
原文: Java加密与解密艺术
编码后: SmF2YeWKoOWvhuS4juino-WvhuiJuuacrw..
解码后: Java加密与解密艺术
--使用Base64编码后得到的是以下信息--
原文: Java加密与解密艺术
编码后: SmF2YeWKoOWvhuS4juino+WvhuiJuuacrw==
解码后: Java加密与解密艺术
Commons Codec实现
import org.apache.commons.codec.binary.Base64;
/**
* URL Base64组件
*
* @author user
*/
public class UrlBase64Coder {
public static final String ENCODING = "UTF-8";
public static String encode(String data) throws Exception {
/* 执行编码 */
byte[] b = Base64.encodeBase64URLSafe(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
public static String decode(String data) throws Exception {
/* 执行解码 */
byte[] b = Base64.decodeBase64(data.getBytes(ENCODING));
return new String(b, ENCODING);
}
}
public class UrlBase64CoderTest {
@Test
public final void test() throws Exception {
String inputStr = "Java加密与解密艺术";
System.err.println("原文:\t" + inputStr);
/* 进行UrlBase64编码 */
String code = UrlBase64Coder.encode(inputStr);
System.err.println("编码后:\t" + code);
/* 进行UrlBase64解码 */
String outputStr = UrlBase64Coder.decode(code);
System.err.println("解码后:\t" + outputStr);
/* 验证UrlBase64编码解码一致性 */
Assert.assertEquals(inputStr, outputStr);
}
}
原文: Java加密与解密艺术
编码后: SmF2YeWKoOWvhuS4juino-WvhuiJuuacrw
解码后: Java加密与解密艺术
与Bouncy Castle方式唯一的差别是否使用“.”符号作为填充符。显然,Commons Codec使用了不定长的URL Base64编码
对于这两种实现,从实用的角度讲,通过Url参数方式传输数据往往要求数据长度尽量缩短,以缩短URL长度,避免网关限制,减少网络传输时间。从这一点将,Commons Codec的Url Base64实现较为实用。
五、应用举例
广泛应用于电子邮件的传输,以及密钥和证书文件的文本保存方式。在数据保密要求强度不高订的情况下,可以使用Base64算法做简单的数据“加密”