2014年6月26日 星期四

【Node.js 小密技】使用 crypto 模組亂數產生字串

Standard
已非常熟悉 Node.js 的人都知道,crypto 模組是一個無中生有的神器。我們可以用它的 API 加工加密資料,也可以解開加密後的包裹。既然和密碼處理相關,當然也有亂數產生器,可供開發者產生一大堆的亂數資料。

如果你需要一個 32Bytes 長度的亂數資料,可以直接呼叫 crypto.randomBytes() 並帶入長度後生成:
var crypto = require('crypto');
var buf = crypto.randomBytes(32);
註:回傳的結果 buf ,是一個 binary buffer,而每一個 Bytes 都會是範圍在 0 ~ 255 (0x00 ~ 0xff)的數字。

不過,在多數應用中,我們更常需要一個亂數字串,而非二進位的亂數資料,這時就需要做一些進一步的加工處理。方法其實不只一種,如建表、取代不可見字元碼等方式都可以,沒有標準做法。但懶惰的開發者們,多半是直接利用 Buffer 內建的 API 來將資料轉換成字串,並指定編碼方式來達成。

下面兩種方法都可行:
buf.toString('hex');
buf.toString('base64');

只是,使用十六進位(hex),會讓你的最後的字串單純只有 0-9 和 a-f 的字元存在,所以使用 base64 是比較好的選擇,讓字串多變並複雜些。

註:base64 編碼是以 6 bits 為單位來進行處理,而 1 Byte 有 8bits。如果你的資料長度非 6 bits 的整數倍長度,base64 會在結尾補上『=』。有些人覺得多了一些『=』符號很醜,就會用 replace() 替代掉或者是一開始就取 6 bits 整數倍長度的亂數資料(如:3 bytes、6 bytes 等等)。

有些情況,我們需要特定長度的亂數字串,也可以搭配使用 substr(),只是要確定生成的字串長度,比我們想要的字串長度還要長。下面的範例,就是取八個字元長度的字串:
buf.toString('base64').substr(0, 8);

當然,若你想要一次搞定,也可以將之前所說的,全部串在一起寫:
var randomString = crypto.randomBytes(32).toString('base64').substr(0, 8);

後記

最近在開發的 Project 中,一直在處理 Token 以及密碼相關的東西,常用到亂數字串。之前用過不少方法,每次要寫不少 code 相當讓人煩燥。所以記錄下來,以後自己直接 copy & paste 即可,也讓有相同需求的人可以直接參考使用。