工具介绍
编码规则
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24 位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个 “=”。
实现的代码:
//下面是64个基本的编码 var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var base64DecodeChars = new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1); //编码的方法 function base64encode(str) { var out, i, len; var c1, c2, c3; len = str.length; i = 0; out = ""; while(i < len) { c1 = str.charCodeAt(i++) & 0xff; if(i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 0x3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if(i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt((c2 & 0xF) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)); out += base64EncodeChars.charAt(c3 & 0x3F); } return out; } //解码的方法 function base64decode(str) { var c1, c2, c3, c4; var i, len, out; len = str.length; i = 0; out = ""; while(i < len) { 53: do { c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while(i < len && c1 == -1); if(c1 == -1) break; 59: do { c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while(i < len && c2 == -1); if(c2 == -1) break; out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); 66: do { c3 = str.charCodeAt(i++) & 0xff; if(c3 == 61) return out; c3 = base64DecodeChars[c3]; } while(i < len && c3 == -1); if(c3 == -1) break; out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); 76: do { c4 = str.charCodeAt(i++) & 0xff; if(c4 == 61) return out; c4 = base64DecodeChars[c4]; } while(i < len && c4 == -1); if(c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4); } return out; } function utf16to8(str) { var out, i, len, c; out = ""; len = str.length; for(i = 0; i < len; i++) { c = str.charCodeAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out += str.charAt(i); } else if (c > 0x07FF) { out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } else { out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } } return out; } function utf8to16(str) { var out, i, len, c; var char2, char3; out = ""; len = str.length; i = 0; while(i < len) { c = str.charCodeAt(i++); switch(c >> 4) { case case case case case case case case 7: // 0xxxxxxx out += str.charAt(i-1); break; case case 13: // 110x xxxx 10xx xxxx char2 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = str.charCodeAt(i++); char3 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; }
调用:
//编码 value = base64encode(utf16to8(src)) //解码 value = utf8to16(base64decode(src))
BASE64编码原理:
Base64是一种加料置位加密法,那为什么叫base64呢?因为无论明文是什么(比如汉字,特殊符号等),加密后的密文都只会变成字母A-Z、a-z和0-9 和+和/这64个字符,被他加密体后积一般会变成原来的4/3。
Base64的标准在RFC2045里的24页可以看到。
http://wenku.baidu.com/view/bd567523aaea998fcc220e8e.html
下面我就来加密一个astralidea的简写AST来说明他的加密原理。
为了说明方便,我们用人的思考方式,而不是计算机的方式,下面是上图的说明。
1.假设有3个字符,首先先将他换成10进制ASCII码,然后转成2进制,少位用0补齐,保证8位。
2.因为ASCII码大小是一字节也就是8位,3个8位。又因为3*8=4*6,我们给他分成4分,每份6位。如果少位都用0补齐。
3.把6位码前2位加两个0,比如010000转完后就是00010000,这对计算机来说比较重要,变成了8位码。
4.将4个8位(也就是一字节)码按照RFC里的BASE64标准换算,下面也提供了标准表。
这样我们就得到了QVNU,也就是AST加密的结果。
下面是标准的BASE64编码表。
那么有3N个字符就是分别把3个转成4个了,那假如有3N+1个字符怎么办呢?
BASE64是这样规定的,剩下的用“=”补齐。
比如A这个字符转后为01000001末尾加4个0变为010000|010000查表得QQ差2个用=补齐。
因此A加密后是QQ==,对于3N+2情况
同理AS加密后为QVM=
这样就有了所有情况了。
说了这么多,我们给出实现加密的代码,从这里更可以看出加密过程简洁的表达:
当然如果你用.net库你可以直接调用
byte[] bytes=Encoding.Default.GetBytes("ConvertString"); Convert.ToBase64String(bytes);
即可。
应用:
1.由于BASE64可以加密任何的字符,那么我们可以把一个小程序比如几K的EXE文件加密,然后就可以发到网页上,因为BASE64标准没有非法字符,放到任何空间都应该不会有问题。然后另一边复制下来解密就OK了,这样可以省得传到网络硬盘各种原因(比如病毒上传失败)之类的问题。
2.BASE64最初是考虑加密后让你不能一眼看出明文是什么而出现的,其最主要的应用当然是加密了,比如迅雷就是通过BASE64加料后加密而实现的。
比如我虚拟一个地址https://www.e-learn.cn/
我们知道这个地址根本不存在,假设我们会了BASE64怎么模拟迅雷的地址呢?
1.迅雷把上面地址加上料AA和ZZ变成:AAhttps://www.e-learn.cn/ZZ
2.把上面的字符加密得:QUFodHRwczovL3d3dy5lLWxlYXJuLmNuL1pa
3.再前面加上thunder://得:thunder://QUFodHRwczovL3d3dy5lLWxlYXJuLmNuL1pa
你会发现加密后的和我虚拟的是一样的。
FLASHGET原理也是一样,只不过加的料为[FLASHGET]。
而QQ旋风干脆不加料,直接就对地址进行BASE64编码了。
3.Asp.Net里的viewstate就是用BASE64加密所得的,如果了解了这个可以把他解密就能得到一个XML文件,找到key-value pairs
4.BASE64变体,上面所说的都是标准的BASE64,如果我们把加密表里的内容替换或打乱顺序就成了变异的BASE64,如Uuencode加密方法原理一样,但是加密表不一样。