「 加密算法 」Base64

clipboard.png

一. 簡介

首先有個小Tips,1個字母字符 = 1個字節(byte) = 8位(bit),這是表示單位.前端

Base64是網絡上最多見的用於傳輸 8bit 的編碼方式之一,Base64就是一種基於64個可打印字符來表示二進制數據的方法。java

在一些網絡傳送渠道,有時候有些的字節字符不能被支持.好比圖片的二進制流的每一個字節不可能所有是可見字符,這種狀況下傳送不了.而Base64的機制就能很好解決這種問題,它不改變原來的協議,在原來的基礎作一種擴展,基於64個可打印字符來表示二進制.node

再者,有時候咱們經過記事本去打開一些圖片或者應用程序,會獲得一大堆看不懂的亂碼,由於二進制文件裏面有不少沒法顯示和打印的字符.因此若是要讓記事本可以處理二進制數據,就可使用Base64來進行轉碼,將不可見的轉成可見的.webpack

二. 算法原理

  1. 咱們拿到一串字符,好比 abcdef.先按ASCII碼編碼.
  2. 它會將字符串按字節數分開,每三個字節爲一組. 3 byte * 8 bit === 24bit.
  3. 在這組中,將24位數據按照每6位爲一組,再次分紅4組.
  4. 而後將這四組的6位數的高位各補兩個0,將其轉爲十進制數.
  5. 進行查表,獲得對應的字符,就是對應的Base64轉化的字符.


那麼有個問題來了,若是原始數據的位數不是3的整數倍怎麼辦,Base會在不足的後面用"="補足,因此這個"="只會存在在Base64碼的最後,而且只會有1或者2個,不可能出如今中間.git

// javaScript實現

if (!Shotgun)
    var Shotgun = {};
if (!Shotgun.Js)
    Shotgun.Js = {};
Shotgun.Js.Base64 = {
    _table: [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
        'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    ],
  
    encode: function (bin) {
        var codes = [];
        var un = 0;
        un = bin.length % 3;
        if (un == 1)
            bin.push(0, 0);
        else if (un == 2)
            bin.push(0);
        for (var i = 2; i < bin.length; i += 3) {
            var c = bin[i - 2] << 16;
            c |= bin[i - 1] << 8;
            c |= bin[i];
            codes.push(this._table[c >> 18 & 0x3f]);
            codes.push(this._table[c >> 12 & 0x3f]);
            codes.push(this._table[c >> 6 & 0x3f]);
            codes.push(this._table[c & 0x3f]);
        }
        if (un >= 1) {
            codes[codes.length - 1] = "=";
            bin.pop();
        }
        if (un == 1) {
            codes[codes.length - 2] = "=";
            bin.pop();
        }
        return codes.join("");
    },
    decode: function (base64Str) {
        var i = 0;
        var bin = [];
        var x = 0, code = 0, eq = 0;
        while (i < base64Str.length) {
            var c = base64Str.charAt(i++);
            var idx = this._table.indexOf(c);
            if (idx == -1) {
                switch (c) {
                    case '=': idx = 0; eq++; break;
                    case ' ':
                    case '\n':
                    case "\r":
                    case '\t':
                        continue;
                    default:
                        throw { "message": "\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u65E0\u6548\u7F16\u7801\uFF1A" + c };
                }
            }
            if (eq > 0 && idx != 0)
                throw { "message": "\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01" };
  
            code = code << 6 | idx;
            if (++x != 4)
                continue;
            bin.push(code >> 16);
            bin.push(code >> 8 & 0xff);
            bin.push(code & 0xff)
            code = x = 0;
        }
        if (code != 0)
            throw { "message": "\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u6570\u636E\u957F\u5EA6\u9519\u8BEF" };
        if (eq == 1)
            bin.pop();
        else if (eq == 2) {
            bin.pop();
            bin.pop();
        } else if (eq > 2)
            throw { "message": "\u0062\u0061\u0073\u0065\u0036\u0034\u002E\u0074\u0068\u0065\u002D\u0078\u002E\u0063\u006E\u0020\u0045\u0072\u0072\u006F\u0072\u003A\u7F16\u7801\u683C\u5F0F\u9519\u8BEF\uFF01" };
  
        return bin;
    }
};

三. 應用

  • Base64編碼可用於在HTTP環境下傳遞較長的標識信息.
  • 電子郵件:有些文本協議不支持不可見字符的傳遞,只能用大於32的可見字符來傳遞信息
  • Base64 也會常常用做一個簡單的「加密」來保護某些數據,而真正的加密一般都比較繁瑣.
  • 垃圾訊息傳播者用Base64來避過反垃圾郵件工具,由於那些工具一般都不會翻譯Base64的訊息.
  • 前端在實現頁面一些比較小的圖片,一般會選擇將圖片內容直接內嵌在頁面中,避免沒必要要的外部資源加載,增大頁面加載時間,可是圖片數據是二進制數據,該怎麼嵌入呢?絕大多數現代瀏覽器都支持一種名爲 Data URLs 的特性,容許使用Base64對圖片或其餘文件的二進制數據進行編碼,將其做爲文本字符串嵌入網頁中。好比webpack工具中的url-loader默認將8kb如下的圖片編譯成Base64碼嵌在引用文件中.

四. 前端應用

crypto-js es6

功能強大,不止處理Base64,支持的模塊很是多,star數目前6k+,先後端可用
github

//後端 npm包管理
npm install crypto-js

import sha256 from 'crypto-js/sha256';
import hmacSHA512 from 'crypto-js/hmac-sha512';
import Base64 from 'crypto-js/enc-base64';

const message, nonce, path, privateKey; // ...
const hashDigest = sha256(nonce + message);
const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));

//前端 Brower管理
bower install crypto-js

js-Base64web

專門處理Base64,目前star數2k+,先後端都可用算法

//安裝
$ npm install --save js-base64
//若是你使用的es6語法,須要轉載這個進行語法轉換
$ npm install --save babel-preset-env

//node.js
var Base64 = require('js-base64').Base64;
//es6+
import { Base64 } from 'js-base64';

//很是輕快的使用體驗
Base64.encode('dankogai');  // ZGFua29nYWk=
Base64.encode('小飼弾');    // 5bCP6aO85by+
Base64.encodeURI('小飼弾'); // 5bCP6aO85by

五. 解密

若是你看懂了以上的算法原理,那麼解密其實不是太大的問題,只要你遵循這個規則進行逆推運算,就能夠獲得原始數據.因此嚴格上說Base64並非什麼加密,只是編譯事後的並非明文而已npm

相關文章
相關標籤/搜索