base64编码方式是一种非常普遍的对字符串进行编码的方法,通常,会有不少加解密算法会使用到base64,比如常用的sha1+base64以及md5+base64。
  其实base64的64指的就是它的编码方法:把输入数据的二进制转换为a-z,A-Z,0-9,+,/再加上一个用来填充的=的字符串。这里刚好有64种不同的字符。所以就这样了。
  它的具体方法是把每6bits的二进制数据按照base64的码表转换成上述字符。因此,刚好每3个字符就会被编码成4个字符,这4个字符就是一个小组,所以自然base64的字符串长度应该是4的倍数。但是实际上当最后一组不够的时候,就会用=来填充满。所以你看到的base64编码后的字符串很可能就会尾随一个==
 
我们先看看base64的码表:
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v    
14 O 31 f 48 w (pad) =
15 P 32 g 49 x    
16 Q 33 h 50 y    
 
 
下面是我根据René Nyffenegger这个人写的算法修改之后直接从传入的MD5 32位的16进制字符串生成Base64编码的算法。
//encode a string of HEX value with base64        
//By Ulysess        
std::string base64_encode_hex(unsigned char const* hex_str_to_encode , unsigned int len){        
        std::string ret;        
        unsigned char char_array_3[3];        
        unsigned char char_array_4[4];        
        unsigned char* hval = new unsigned char[len/2];        
    
        bool token = true;        
        unsigned char temp = '0';        
    
        //transform the string into a HEX char*        
        for(int i = 0; i < len ; i++){        
                switch (hex_str_to_encode[i]) {        
                        case 'a':        
                        case 'A': temp = 10; break;        
                        case 'b':        
                        case 'B': temp = 11; break;        
                        case 'c':        
                        case 'C': temp = 12; break;        
                        case 'd':        
                        case 'D': temp = 13; break;        
                        case 'e':        
                        case 'E': temp = 14; break;        
                        case 'f':        
                        case 'F': temp = 15; break;        
                        case '0':        
                        case '1':        
                        case '2':        
                        case '3':        
                        case '4':        
                        case '5':        
                        case '6':        
                        case '7':        
                        case '8':        
                        case '9': temp = hex_str_to_encode[i] - '0'; break;        
                        default: return 0;        
                }        
                if(token){        
                        token = false;        
                        hval[i/2] = temp * 16;        
                } else {        
                        token = true;        
                        hval[i/2] += temp;        
                }        
        }        
    
        int in_len = len/2;        
        int i = 0, j = 0;        
        while (in_len--) {        
                char_array_3[i++] = *(hval++);        
                if (i == 3) {        
                        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;        
                        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);        
                        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);        
                        char_array_4[3] = char_array_3[2] & 0x3f;        
    
                        for(i = 0; (i <4) ; i++)        
                        ret += base64_chars[char_array_4[i]];        
                        i = 0;        
                }        
        }        
    
        if (i){        
        for(j = i; j < 3; j++)        
                char_array_3[j] = '\0';        
    
        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;        
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);        
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);        
        char_array_4[3] = char_array_3[2] & 0x3f;        
    
        for (j = 0; (j < i + 1); j++)        
            ret += base64_chars[char_array_4[j]];        
    
        while((i++ < 3))        
            ret += '=';        
    
        }        
    
        return ret;        
    
}    
 
下面这个是网上流传的一个SHA1 和MD5 加密以及再进行base64编码的JavaScript脚本:
/*sha1    
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined    
* in FIPS PUB 180-1    
* Version 2.1a Copyright Paul Johnston 2000 - 2002.    
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet    
* Distributed under the BSD License    
* See http://pajhome.org.uk/crypt/md5 for details.    
*/
    
    
/*    
* Configurable variables. You may need to tweak these to be compatible with    
* the server-side, but the defaults work in most cases.    
*/
    
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase                */    
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance     */    
var chrsz     = 8; /* bits per input character. 8 - ASCII; 16 - Unicode            */    
    
/*    
* These are the functions you'll usually want to call    
* They take string arguments and return either hex or base-64 encoded strings    
*/
    
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}        
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}        
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}        
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}        
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}        
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}        
    
/*    
* Perform a simple self-test to see if the VM is working    
*/
    
function sha1_vm_test() {        
        return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";        
}        
    
/*    
* Calculate the SHA-1 of an array of big-endian words, and a bit length    
*/
    
function core_sha1(x, len) {        
        /* append padding */    
        x[len >> 5] |= 0x80 << (24 - len % 32);        
        x[((len + 64 >> 9) << 4) + 15] = len;        
                
        var w = Array(80);        
        var a = 1732584193;        
        var b = -271733879;        
        var c = -1732584194;        
        var d = 271733878;        
        var e = -1009589776;        
                
        for(var i = 0; i < x.length; i += 16) {        
                var olda = a;        
                var oldb = b;        
                var oldc = c;        
                var oldd = d;        
                var olde = e;        
                
                for(var j = 0; j < 80; j++) {        
                        if(j < 16) w[j] = x[i + j];        
                        else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);        
                        var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));        
                        e = d;        
                        d = c;        
                        c = rol(b, 30);        
                        b = a;        
                        a = t;        
                }        
                
                a = safe_add(a, olda);        
                b = safe_add(b, oldb);        
                c = safe_add(c, oldc);        
                d = safe_add(d, oldd);        
                e = safe_add(e, olde);        
        }        
        return Array(a, b, c, d, e);        
}        
    
/*    
* Perform the appropriate triplet combination function for the current    
* iteration    
*/
    
function sha1_ft(t, b, c, d) {        
        if(t < 20) return (b & c) | ((~b) & d);        
        if(t < 40) return b ^ c ^ d;        
        if(t < 60) return (b & c) | (b & d) | (c & d);        
        return b ^ c ^ d;        
}        
    
/*    
* Determine the appropriate additive constant for the current iteration    
*/
    
function sha1_kt(t) {        
        return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :        
                         (t < 60) ? -1894007588 : -899497514;        
}        
    
/*    
* Calculate the HMAC-SHA1 of a key and some data    
*/
    
function core_hmac_sha1(key, data) {        
        var bkey = str2binb(key);        
        if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);        
                
        var ipad = Array(16), opad = Array(16);        
        for(var i = 0; i < 16; i++) {        
                ipad[i] = bkey[i] ^ 0x36363636;        
                opad[i] = bkey[i] ^ 0x5C5C5C5C;        
        }        
                
        var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);        
        return core_sha1(opad.concat(hash), 512 + 160);        
}        
    
/*    
* Add integers, wrapping at 2^32. This uses 16-bit operations internally    
* to work around bugs in some JS interpreters.    
*/
    
function safe_add(x, y) {        
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);        
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);        
        return (msw << 16) | (lsw & 0xFFFF);        
}        
    
/*    
* Bitwise rotate a 32-bit number to the left.    
*/
    
function rol(num, cnt) {        
        return (num << cnt) | (num >>> (32 - cnt));        
}        
    
/*    
* Convert an 8-bit or 16-bit string to an array of big-endian words    
* In 8-bit function, characters >255 have their hi-byte silently ignored.    
*/
    
function str2binb(str) {        
        var bin = Array();        
        var mask = (1 << chrsz) - 1;        
        for(var i = 0; i < str.length * chrsz; i += chrsz)        
                bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);        
        return bin;        
}        
    
/*    
* Convert an array of big-endian words to a string    
*/
    
function binb2str(bin) {        
        var str = "";        
        var mask = (1 << chrsz) - 1;        
        for(var i = 0; i < bin.length * 32; i += chrsz)        
                str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);        
        return str;        
}        
    
/*    
* Convert an array of big-endian words to a hex string.    
*/
    
function binb2hex(binarray) {        
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";        
        var str = "";        
        for(var i = 0; i < binarray.length * 4; i++) {        
                str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +        
                             hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);        
        }        
        return str;        
}        
    
/*    
* Convert an array of big-endian words to a base-64 string    
*/
    
function binb2b64(binarray) {        
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";        
        var str = "";        
        for(var i = 0; i < binarray.length * 4; i += 3) {        
                var triplet = (((binarray[i     >> 2] >> 8 * (3 - i     %4)) & 0xFF) << 16)        
                                        | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )        
                                        | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);        
                for(var j = 0; j < 4; j++) {        
                        if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;        
                        else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);        
                }        
        }        
        document.write(str);        
        return str;        
}        
    
    
/*md5    
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message    
* Digest Algorithm, as defined in RFC 1321.    
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.    
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet    
* Distributed under the BSD License    
* See http://pajhome.org.uk/crypt/md5 for more info.    
*/
    
    
/*    
* Configurable variables. You may need to tweak these to be compatible with    
* the server-side, but the defaults work in most cases.    
*/
    
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase                */    
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance     */    
var chrsz     = 8; /* bits per input character. 8 - ASCII; 16 - Unicode            */    
    
/*    
* These are the functions you'll usually want to call    
* They take string arguments and return either hex or base-64 encoded strings    
*/
    
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}        
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}        
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}        
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }        
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }        
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }        
    
/*    
* Perform a simple self-test to see if the VM is working    
*/
    
function md5_vm_test() {        
        return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";        
}        
    
/*    
* Calculate the MD5 of an array of little-endian words, and a bit length    
*/
    
function core_md5(x, len) {        
        /* append padding */    
        x[len >> 5] |= 0x80 << ((len) % 32);        
        x[(((len + 64) >>> 9) << 4) + 14] = len;        
                
        var a = 1732584193;        
        var b = -271733879;        
        var c = -1732584194;        
        var d = 271733878;        
                
        for(var i = 0; i < x.length; i += 16) {        
                var olda = a;        
                var oldb = b;        
                var oldc = c;        
                var oldd = d;        
                
                a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);        
                d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);        
                c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);        
                b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);        
                a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);        
                d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);        
                c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);        
                b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);        
                a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);        
                d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);        
                c = md5_ff(c, d, a, b, x[i+10], 17, -42063);        
                b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);        
                
                a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);        
                d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);        
                c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);        
                b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);        
                
                a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);        
                d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);        
                c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);        
                b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);        
                a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);        
                d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);        
                c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);        
                b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);        
                a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);        
                d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);        
                c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);        
                b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);        
                a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);        
                d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);        
                c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);        
                b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);        
                
                a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);        
                d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);        
                c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);        
                b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);        
                a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);        
                d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);        
                c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);        
                b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);        
                a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);        
                d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);        
                c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);        
                b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);        
                a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);        
                d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);        
                c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);        
                b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);        
                
                a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);        
                d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);        
                c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);        
                b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);        
                a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);        
                d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);        
                c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);        
                b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);        
                a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);        
                d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);        
                c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);        
                b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);        
                a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);        
                d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);        
                c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);        
                b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);        
                
                a = safe_add(a, olda);        
                b = safe_add(b, oldb);        
                c = safe_add(c, oldc);        
                d = safe_add(d, oldd);        
        }        
        return Array(a, b, c, d);        
}        
    
/*    
* These functions implement the four basic operations the algorithm uses.    
*/
    
function md5_cmn(q, a, b, x, s, t) {        
        return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);        
}        
function md5_ff(a, b, c, d, x, s, t) {        
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);        
}        
function md5_gg(a, b, c, d, x, s, t) {        
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);        
}        
function md5_hh(a, b, c, d, x, s, t) {        
        return md5_cmn(b ^ c ^ d, a, b, x, s, t);        
}        
function md5_ii(a, b, c, d, x, s, t) {        
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);        
}        
    
/*    
* Calculate the HMAC-MD5, of a key and some data    
*/
    
function core_hmac_md5(key, data) {        
        var bkey = str2binl(key);        
        if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);        
                
        var ipad = Array(16), opad = Array(16);        
        for(var i = 0; i < 16; i++) {        
                ipad[i] = bkey[i] ^ 0x36363636;        
                opad[i] = bkey[i] ^ 0x5C5C5C5C;        
        }        
                
        var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);        
        return core_md5(opad.concat(hash), 512 + 128);        
}        
    
/*    
* Add integers, wrapping at 2^32. This uses 16-bit operations internally    
* to work around bugs in some JS interpreters.    
*/
    
function safe_add(x, y) {        
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);        
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);        
        return (msw << 16) | (lsw & 0xFFFF);        
}        
    
/*    
* Bitwise rotate a 32-bit number to the left.    
*/
    
function bit_rol(num, cnt) {        
        return (num << cnt) | (num >>> (32 - cnt));        
}        
    
/*    
* Convert a string to an array of little-endian words    
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.    
*/
    
function str2binl(str) {        
        var bin = Array();        
        var mask = (1 << chrsz) - 1;        
        for(var i = 0; i < str.length * chrsz; i += chrsz)        
                bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);        
        return bin;        
}        
    
/*    
* Convert an array of little-endian words to a string    
*/
    
function binl2str(bin) {        
        var str = "";        
        var mask = (1 << chrsz) - 1;        
        for(var i = 0; i < bin.length * 32; i += chrsz)        
                str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);        
        return str;        
}        
    
/*    
* Convert an array of little-endian words to a hex string.    
*/
    
function binl2hex(binarray) {        
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";        
        var str = "";        
        for(var i = 0; i < binarray.length * 4; i++)        
        {        
                str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +        
                             hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);        
        }        
        return str;        
}        
    
/*    
* Convert an array of little-endian words to a base-64 string    
*/
    
function binl2b64(binarray) {        
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";        
        var str = "";        
        for(var i = 0; i < binarray.length * 4; i += 3) {        
                var triplet = (((binarray[i     >> 2] >> 8 * ( i     %4)) & 0xFF) << 16)        
                                        | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )        
                                        | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);        
                for(var j = 0; j < 4; j++) {        
                        if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;        
                        else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);        
                }        
        }        
        document.write(str);        
        return str;        
}