1. 程式人生 > >JS版SM2國密演算法的簽名驗證

JS版SM2國密演算法的簽名驗證

前段時間因工作需要,瞭解到在Github上已經有人實現了用JavaScript來寫簽名和驗籤,支援RSA、ECC、DSA等演算法,還能解析X.509證書,一時覺得JavaScript是無比強大。後面就研究了下JavaScript版的ECC演算法簽名驗證,自己再擴充套件實現了SM2國密演算法的簽名驗證。

基於現有已實現的C#版SM2國密演算法的簽名驗證,再結合原來JavaScript的ECC演算法,使用JavaScript實現SM2國密演算法的簽名驗證相對簡單,只需要將C#語言翻譯成JavaScript語言實現。不過中間還是遇到了些問題,主要是在JavaScript計算SM3摘要值大數的運算上還是有些不同。

1)JS計算SM3摘要

在做SM2簽名之前,需要先計算出原始資料的SM3摘要值,需要計算出z值,這其中就用到了大量的移位運算。JavaScript本身支援移位異或運算,但在C#中數字有int、long等多種型別,而在JavaScript中都用Number型別,這些不同型別運算要分別處理。C#的long型別表示64位有符號的整數,為區分32位整數在值後面加L顯示定義。而在JavaScript就要把整數轉成64位長度來計算。

C#中預設不檢查運算上溢\下溢,除開使用常量編譯器會提示,或顯示使用了checked關鍵字檢查溢位。原來在C#中使用int型別運算的,並在計算後可能會超出Int32.MinValue~Int32.MaxValue範圍的,在JavaScript中就需要擷取超出32位長度的高位。並且要按優先順序計算,即a+b+c必須先計算出(a+b)結果是否溢位再加c,不能直接先計算(a+b+c)總結果再計算溢位後32位的值。因此我用JavaScript寫了個C#中的unchecked情況下Int32位數字溢位後轉換的值。

而C#中原來的byte[]在JavaScript裡變成了Array陣列,原來C#中使用的BigInteger大數計算類也原封不動移到了JavaScript中來,還有ECC曲線的Curve、ECPoint物件等等,這樣只需要註冊SM3、SM2演算法再實現就可以了,原來C#中SM2演算法就不在此敘述了。

2)SM2簽名用的隨機數

原來在SM2測試曲線的示例中,有人提出每次簽名的結果是一樣的。後面發現那裡簽名時用的k是固定值,所以只要簽名金鑰和原始資料沒變,每次簽名後的結果都是一樣的。SM2國密標準裡用的k值是隨機生成的,所以SM2國密演算法的簽名結果每次都不一樣。而SM2國密演算法的加密中也生成了隨機數,因此每次SM2加密結果也都不一樣。

3)JS的SM2演算法應用

JavaScript實現SM2國密演算法的簽名和驗證現在應用得比較少,一般來說簽名使用的私鑰都封在UKey安全裝置中了,為保證安全性硬體本身提供了演算法介面,很少使用軟演算法實現。不過JavaScript作為客戶端的指令碼語言,可以在提交到伺服器端前對資料進行加密,這個還是非常有意義的,比如可以在客戶端使用公鑰加密賬號資訊,然後在伺服器端用私鑰進行解密。

最後,提供一個SM2國密演算法的SM2證書驗籤功能的Demo,完整的SM2的金鑰對生成、簽名、驗證點這裡下載。

SM2簽名驗證
  • (Base64)
  • (Base64)

若IE瀏覽器下驗證簽名時提示停止執行此指令碼,請選擇否(N)繼續執行。