不同函式庫算出來的CRC數值不同?如何使用Node.js計算正確的CRC?


循環冗餘校驗(CRC, Cyclic Redundancy Check)是一種簡單快速的雜湊函數,可以藉由比對資料傳輸或是儲存前後的循環冗餘校驗碼,檢測其是否有錯誤發生。常被用來作為伺服器應用為目的來使用的Node.js,會有很大的機會需要使用CRC進行一些計算。可惜的是,Node.js雖然可以藉由內建的「Crypto」模組來使用許多常見的雜湊函數計算資料的校驗和(checksum),但就是不支援CRC。那麼如果要在Node.js上計算CRC,該怎麼做比較好呢?

首先我們需要知道CRC演算法,實際上分了許多不同版本的函數,如8位元的CRC8、16位元的CRC16、32位元的CRC32、64位元的CRC64,CRC的位元數愈高,雜湊出來的數值碰撞機率自然會比較低,但會需要更多的時間去運算。但是CRC也不完全是使用位元數量去做變化,很有可能會遇到同樣的資料,A函式庫算出來的CRC32和B函式庫算出來的CRC32結果不同的情形。舉例來說,請看以下的PHP程式:

執行結果為:

d87f7e0c, accf8b33, d87f7e0c

不曉得大家有沒有發現?同樣都是CRC32,字串「test」在上面程式中似乎可以算出「d87f7e0c16」和「accf8b3316」這兩種結果。這是由於除了CRC的位元數量之外,還有其他變數在影響著CRC演算法的計算結果。

大體來說,若不包含準備進行CRC計算的資料的話,會影響CRC演算法結果的變數共有五個,分別是「位元數量」、「多項式」、「起始值」、「終止XOR值」和「是否反射」。

藉由調控這五個變數,可以衍生出各種版本的CRC雜湊函數,於是會細分成CRC8-ATMCRC8-CDMA、CRC16-CCITT、CRC32-IEEE、CRC32-CCRC64-ECMA、CRC64-ISO等等十分雜亂的CRC函數名稱

順帶一題,「mhash」函式庫的「CRC32」函數算是比較特別的,並沒有其他常見的CRC函式庫可以算出跟「mhash」函式庫一樣的結果。於是在乎這點的程式設計師多半就會使用比較標準的「CRC32B」去計算CRC校驗和,以求在不同的平台上也能一致。但也是有沒發現到或是不在乎這個問題的程式設計師依舊使用mhash函式庫的「CRC32」函數,導致與其他系統串接時雙方可能都會有一些障礙。

回到Node.js的主題上,若要在Node.js上實作CRC演算法,最好是能將先前提到的五個變數考慮進去,確保演算法去串接其他人實作的CRC函數之相容性。至於實作的方式本篇文章將不會介紹,本篇文章要介紹的是「node-crc」這個模組。

node-crc

node-crc」是一個使用Node.js 8之後才支援的N-API所開發的模組,使用C語言實作出各種不同版本的CRC函數,並且可用「位元數量」、「多項式」、「起始值」、「終止XOR值」和「是否反射」這五個變數來控制輸出結果。

GitHub:

https://github.com/magiclen/node-crc

npm:

https://www.npmjs.com/package/node-crc

安裝

直接使用npm指令進行安裝:

npm install --save node-crc

用法

初始化

使用「require」函數來引入「node-crc」模組。

計算CRC校驗和

使用模組的「crc」函數可以傳入「位元數量」、「多項式」、「起始值」、「終止XOR值」和「是否反射」這五個變數以及要計算的資料Buffer來計算出該資料的CRC校驗和,結果會以Buffer的型態回傳。

模組同時也提供數個常見的CRC函數,可直接被呼叫使用,列表如下:

用法如下:

關於作者

Magic Len

Magic Len

各位好,我是Magic Len,是這網站的管理員。我是台灣台中大肚山上人,畢業於台中高工資訊科和台灣科技大學資訊工程系,曾在桃機航警局服役。我熱愛自然也熱愛科學,喜歡和別人分享自己的知識與經驗。如果你有興趣認識我,可以加我的Facebook,並且請註明是從MagicLen來的。

相關文章