一、什么是Base64编码
Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64 主要不是加密,它主要的用途是把一些二进制数转成普通字符用于网络传输。 由于一些二进制字符在传输协议中属于控制字符,不能直接传送需要转换一下。Base64编码就是把二进制字节序列转化为ASCII字符序列。一般增加1/3长度,而且也是不可读的。 使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
二、Base64原理
[源数据]
——>[获得源数据的二进制流]
——>[每3个8位二进制转换为4个6位二进制]
——>[每6位二进制转换为十进制]
——>[对照表转换为Base64数据]
关键点:3个8位二进制转换4个6位二进制的方法 将输入的二进制数据流以每次读取6个bit的方式读取,不足6位的后补0,将每3个8位二进制转换为4个6位二进制,也就是说每3个8位字节将编码为4个6位字节(3×8 → 4×6);不满4个字节的以“=”填充。其实这4个六位字节仍然是8位,只不过高两位被设置为0。当一个字节只有6位有效时,它的取值空间为0 到 2的6次方减1 即63,也就是说被转换的Base64编码的每一个编码的取值空间为(0-63)。事实上,0-63之间的ASCII码有许多不可见字符,所以应该再做一个映射,映射表(码表)为:
码字 | 个数 | ASCII码 | 对应的6bit值 |
---|---|---|---|
0 - 9 | 10个 | 48 - 57 | 52 - 61 |
A - Z | 26个 | 65 - 90 | 0 - 25 |
a - z | 26个 | 96 - 122 | 26 - 51 |
+ | 1个 | 43 | 62 |
/ | 1个 | 47 | 63 |
三、Base64应用
1.mail
由于rfc821有以下两条限制:
1)邮件的内容必须全部为7-比特的美国ascii码。
2)每一行的长度不能超过1000的字符 当邮件中有其他的非ASCII字符或二进制数据时,就需要做转换。这个就叫做Content-Transfer-Encoding,Base64就是其中的一种方法。在firefox你可以设置自己发送邮件的内容传输编码方式。在收到的邮件里,你可以查看邮件原文,看看原文的编码。
2.URL
有些应用需要把二进制数据放到URL里,URL只能是特定的一些ASCII字符。这时候,也需要用到BASE64编码。当然这也只是对二进制数据本身的编码,编码后的数据里面可能包含+/,真正放到URL里面时候,还需要URL-Encoding,变成%XX模式。
3.HTML中内嵌图片
就是说这种状况下,图片不是以链接地址的方式嵌到HTML中去的,图片本身已被BASE64成字符串放到HTML页面文本中去了,成为HTML文本的一部分。当HTML页面拉取完成之后,图片数据也就下来了,不再需要再去拉取图片.如下格式:
<img src='data:image/png;base64,base64code'>
这种标签图片的显示需要浏览器的支持,先Base64解码,再去显示不同格式的图片。 使用data: URI
直接在网页中嵌入,data: URI
定义于IETF标准的RFC 2397。 data: URI
的基本使用格式如下:
data:[<MIME-type>][;base64|charset=some_charset],<data>
mime-type是嵌入数据的mime类型,比如png图片就是image/png。如果后面跟base64,说明后面的data是采用base64方式进行编码的。 获得图片的base64编码,base64编码工具不少,对于前端制作,下面这个本地图片base64编码获取页面是值得推荐的: *Encode Data URL By PuterJam *。
4.简单加密
迅雷等下载工具,就有他们自己特有的下载链接,如thunder://
其实就是把一个HTTP URL资源地址加上了某些东西后再进行BASE64编码,然后加上thunder://
头。 垃圾讯息传播者用Base64来避过反垃圾邮件工具,因为那些工具通常都不会翻译Base64的讯息。
5.百度地图地址转化
百度地图api的地址转化(例如gps坐标->百度地图坐标)结果,使用了base64加密。
四、Java编码实现
1 /** 2 * 3 * @ClassName: SecurityBase64 4 * @Description: 用于编码请求参数 5 * @author BuilderQiu 6 * @date 2013-9-23 上午10:52:1 7 */ 8 public class SecurityBase64 { 9 //对照表 10 private static String base64hash = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/"; 11 //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/"; 12 private SecurityBase64(){} 13 private static class TEMP{ 14 public static final SecurityBase64 instance = new SecurityBase64(); 15 } 16 public static Security getInstance(){ 17 return TEMP.instance; 18 } 19 private void checkSecurity(){ 20 if("".equals(base64hash)||base64hash==null||base64hash.length()!=64){ 21 throw new RuntimeException(Security.class+"was initialize failed!"); 22 } 23 } 24 /** 25 * 26 * @Title: encode 27 * @Description: 编码 28 * @param @param src 29 * @param @return 30 * @return String 31 * @throws 32 */ 33 public String encode(String src){ 34 checkSecurity(); 35 StringBuilder result = new StringBuilder(); 36 byte[] bytes = src.getBytes(); 37 int length = bytes.length; 38 int mod = 0; 39 byte prev = 0; 40 for(int i=0;i<length;i++){ 41 mod = i%3; 42 if(mod==0){ 43 result.append(base64hash.charAt((bytes[i] >> 2) & 0x3F)); 44 }else if(mod==1){ 45 result.append(base64hash.charAt((prev << 4 | bytes[i] >> 4 &0x0F )& 0x3F)); 46 }else{ 47 result.append(base64hash.charAt((bytes[i] >> 6 & 0x03 | prev << 2) & 0x3F)); 48 result.append(base64hash.charAt(bytes[i] & 0x3F)); 49 } 50 prev = bytes[i]; 51 } 52 if(mod==0){ 53 result.append(base64hash.charAt(prev << 4 & 0x3C)); 54 result.append("=="); 55 }else if(mod==1){ 56 result.append(base64hash.charAt(prev << 2 & 0x3F)); 57 result.append("="); 58 } 59 return result.toString(); 60 } 61 /** 62 * 63 * @Title: decode 64 * @Description: 解码 65 * @param @param src 66 * @param @return 67 * @return String 68 * @throws 69 */ 70 public String decode(String src){ 71 if(StringUtil.isBlank(src)){ 72 return ""; 73 } 74 checkSecurity(); 75 byte temp = 0; 76 String result = ""; 77 for(int i=0;i<src.length();i++){ 78 temp = (byte) base64hash.indexOf(src.charAt(i)); 79 if(temp==-1){ 80 result+="000000"; 81 }else{ 82 String t = Integer.toBinaryString(temp); 83 if(t.length()==7){ 84 t = t.substring(1); 85 }else if(t.length()==8){ 86 t = t.substring(2); 87 } 88 while(t.length()<6){ 89 t = "0"+t; 90 } 91 result+=t; 92 } 93 } 94 while(result.endsWith("00000000")){ 95 result = result.substring(0,result.length()-8); 96 } 97 byte[] bytes = new byte[result.length()/8]; 98 for(int i=0;i<bytes.length;i++){ 99 bytes[i]= Integer.valueOf(result.substring(i*8,(i+1)*8),2).byteValue(); 100 } 101 return new String(bytes); 102 } 103 public void setBase64hash(String base64hash) { 104 Security.base64hash = base64hash; 105 } 106 /** 107 * 108 * @Title: randomTable 109 * @Description: 生成随机对照表 110 * @param @return 111 * @return String 112 * @throws 113 */ 114 public static String randomTable(){ 115 String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-/"; 116 List<Character> list = new ArrayList<Character>(); 117 for(int i=0;i<base.length();i++){ 118 list.add(base.charAt(i)); 119 } 120 Collections.shuffle(list); 121 base = ""; 122 for(Character ch:list){ 123 base += ch; 124 } 125 return base; 126 } 127 }