詳解Node.js 中使用 ECDSA 簽名遇到的坑

這篇文章主要介紹了詳解Node.js 中使用 ECDSA 簽名遇到的坑,主要是使用 Node.js 的 Crypto 模塊無法校驗網絡傳輸過來的簽名結果,感興趣的小夥伴們可以參考一下

最近有個朋友問我關於 Node.js 下使用 ECDSA 的問題,主要是使用 Node.js 的 Crypto 模塊無法校驗網絡傳輸過來的簽名結果。在踩坑無數後,終於搞清楚了原因。

坑 0x00:簽名輸出格式

在排除了證書、消息不一致的可能之後,我開始對比使用 Node.js 簽名的結果與網絡傳輸過來的簽名,發現長度不一致,大約差了5~7個字節。於是去網上搜索了一下,才知道原來 Node.js (基於 OpenSSL)簽名得到的是 DER 格式的內容,而網絡上常用的 ECDSA 簽名結果是 IEEE P1363 格式的。(也可以寫作 R|S)

參考:https://stackoverflow.com/a/39575576

知道問題了就好解決了。但是,DER 和 IEEE P1363 兩個格式互轉也不是那麼容易的。

簡單科普一下,ECDSA 是指基於 ECC 橢圓加密算法的簽名方式,簽名結果是兩個整數 R 和 S。 R 和 S 一般長度相同,或者接近。如果長度不同,在各自前面補字節 0x00 直到等長。把 R 和 S 以大頭字節序表示,然後依次前後拼接,就是所謂 IEEE P1363 格式。

坑 0x01:DER 的整數問題

先來了解一下 ECDSA 的 DER 輸出格式,大概如下:

SEQUENCE <LENGTH>
 INTEGER <INTEGER_LENGTH> <INTEGER_VALUE...> # 整數 R
 INTEGER <INTEGER_LENGTH> <INTEGER_VALUE...> # 整數 S

其中

SEQUENCE 是 DER 數組(串?)標頭,用一個字節 0x30 表示

<LENGTH> 是 SEQUENCE 的長度,用一個字節表示,不包括標頭和這個長度本身

INTEGER 是整數標頭,用一個字節 0x02 表示

<INTEGER_LENGTH> 是整數的字節長度,用一個字節表示。

<INTEGER_VALUE> 是整數的內容,以大頭字節序表示。

另一個坑我也已經寫出來了,不知道有人發現沒有?沒想到的話,繼續往下。

IEEE P1363 格式下,R 和 S 都是等長的。所以只要把 IEEE P1363 格式的簽名從中間切分就可以得到 R 和 S 的內容了。而且 IEEE P1363 格式下,R 和 S 也是以大頭字節序表示的,因此沒有字節序轉換問題了。現在,只需要按上面的格式構造一個 DER 即可。

坑 0x01.0:缺少整數前置字節 0x00

我第一次嘗試將 IEEE P1363 格式的簽名轉換成 DER 格式,並沒有失敗,但是當我換一個簽名結果,卻失敗了……我對比了 DER 和 IEEE P1363 的區別,發現了一個特點,在 DER 格式下,R 和 S 偶爾會有前置字節 0x00,但不是一定的。

查資料後才明白,DER 下沒有“無符號整數”之說,也就是說整數都是有符號的。如果 INTEGER 所表示的整數最高字節大於 0x7F,也就是最高位(符號位)爲 1,則表示負數。如果要表示正數,必須在前面補一個字節 0x00……

參考 https://bitcointalk.org/index.php?topic=215205.msg2258789#msg2258789

坑 0x01.1:多餘的整數前置字節 0x00

在我修改代碼後,雖然提高了成功率,可仍然有失敗的情況,仔細看了下,原來是因爲 IEEE P1363 格式裏,R 和 S 可能被補了不止 1 個字節 0x00……

而 DER 下雖然要求補字節 0x00,卻是有且只能有一個字節 0x00。

到此,問題都解決了——直到我測試了 521-bit (是的,你沒看錯,不是 512) 長度的密鑰時,完全失敗,毫無例外。

坑 0x02:DER SEQUENCE 的長度超過 0x7F

前面說了,<LENGTH> 只能用一個字節表示,這是一個整數,前文我提到的整數正負問題,這裏也存在!

即是說,ECDSA 簽名使用 DER 輸出格式時,如果使用 521-bit (是的,你沒看錯,不是 512) 長度的密鑰時,DER的長度將超出 0x7F,使得 <LENGTH> 變成了負數!

而解決方案不是補字節 0x00,而是用字節 0x81 填充 <LENGTH>,再在下一個字節用一個無符號整數的表示長度(0 ~ 255)。

參考:https://stackoverflow.com/a/47099047

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持神馬文庫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章