使用WebCrypto API的电子签名
有時(shí)我們需要讓用戶進(jìn)行電子簽名。 通常,人們會(huì)理解為將您的手寫(xiě)簽名以某種方式放在屏幕上。 根據(jù)管轄范圍,可能很好,或者僅存儲(chǔ)圖像可能還不夠。 例如,在歐洲,有910/2014號(hào)法規(guī) ,該法規(guī)定義了什么是電子簽名。 從法律文本可以預(yù)期到,該定義相當(dāng)模糊:
“電子簽名”是指電子形式的數(shù)據(jù),該數(shù)據(jù)附加到電子形式的其他數(shù)據(jù)上或與之邏輯關(guān)聯(lián),并由簽字人用來(lái)簽名;
是的,再讀幾次,再說(shuō)幾次“ wat”,讓我們討論一下這是什么意思。 它基本上可以表示任何東西。 僅將繪制的簽名的圖像(例如使用html畫(huà)布)附加到數(shù)據(jù)上并且仍然可以計(jì)數(shù),這在技術(shù)上是可以接受的。
但是,當(dāng)我們使用更具體的電子簽名類型-高級(jí)和合格的電子簽名時(shí),情況會(huì)好一些:
高級(jí)電子簽名應(yīng)滿足以下要求:
(a)它與簽字人有獨(dú)特的聯(lián)系;
(b)有能力識(shí)別簽字人; (c)使用電子簽名創(chuàng)建數(shù)據(jù)創(chuàng)建的,簽名者可以在其唯一的控制下以高度的信心使用該簽名; 和 (d)它以這種方式鏈接到與其簽名的數(shù)據(jù),以便可以檢測(cè)到該數(shù)據(jù)的任何后續(xù)更改。
從技術(shù)意義上講,這看起來(lái)像是正確的“數(shù)字簽名”,例如,使用私鑰進(jìn)行簽名,并使用公共密鑰來(lái)驗(yàn)證簽名。 “合格”簽名需要由合格的提供者發(fā)出,該提供者基本上是一個(gè)受信任的證書(shū)頒發(fā)機(jī)構(gòu)。 必須在安全設(shè)備(智能卡和HSM)上發(fā)布用于放置合格簽名的密鑰,以便除所有者外,其他任何人都不能訪問(wèn)私鑰。
但是,高級(jí)簽名和合格簽名之間的法律區(qū)別尚不完全清楚–該法規(guī)明確指出,非合格簽名也具有法律價(jià)值。 在瀏覽器中使用合格的簽名(帶有智能卡)會(huì)給用戶帶來(lái)可怕的體驗(yàn)-在大多數(shù)情況下,它會(huì)通過(guò)Java Applet進(jìn)行,而Java Applet僅可在Internet Explorer和當(dāng)今的特殊Firefox版本上運(yùn)行。 替代方案包括處理簽名的桌面軟件和本地服務(wù)JWS應(yīng)用程序,但是智能卡目前是一個(gè)大問(wèn)題,而且話題不多。
那么,我們?nèi)绾卧试S用戶“放置”電子簽名? 我有一個(gè)想法,那就是可以完全使用WebCrypto API來(lái)完成此工作,如今,WebCrypto API在瀏覽器中或多或少地得到了支持。 這個(gè)想法如下:
- 讓用戶輸入密碼以作弊
- 從密碼中獲取密鑰(例如,使用PBKDF2)
- 使用派生密鑰在用戶提交的表單內(nèi)容上簽名
- 將簽名與其余表單數(shù)據(jù)一起存儲(chǔ)
- (可選)存儲(chǔ)派生密鑰以進(jìn)行驗(yàn)證
這是實(shí)現(xiàn)該流程的javascript要點(diǎn) 。
許多片段來(lái)自非常有用的webcrypto示例存儲(chǔ)庫(kù) 。 hex2buf,buf2hex和str2ab函數(shù)是實(shí)用程序(可惜在js中不是標(biāo)準(zhǔn)的)。
即使有點(diǎn)冗長(zhǎng),代碼的作用也很簡(jiǎn)單。 所有操作都使用Promise和“ then”鏈接在一起,說(shuō)實(shí)話,這對(duì)編寫(xiě)和閱讀非常繁瑣(但我想不可避免):
- 密碼作為原始密鑰加載(轉(zhuǎn)換為數(shù)組緩沖區(qū)后)
- 使用PBKDF2導(dǎo)出一個(gè)秘密密鑰(具有100次迭代)
- 密鑰用于對(duì)用戶填寫(xiě)的內(nèi)容進(jìn)行HMAC“簽名”
- 簽名和密鑰被存儲(chǔ)(在此示例中的UI中)
- 然后可以使用以下數(shù)據(jù)驗(yàn)證簽名:數(shù)據(jù),簽名和密鑰
您可以在這里進(jìn)行測(cè)試:
存儲(chǔ)簽名應(yīng)足以滿足“電子簽名”的定義。 這是只有用戶知道的秘密密碼,甚至可能意味著這是“高級(jí)電子簽名”。 存儲(chǔ)派生的秘密密鑰是有問(wèn)題的–如果存儲(chǔ)它,則意味著您可以代表用戶“偽造”簽名。 但是,不存儲(chǔ)它意味著您無(wú)法驗(yàn)證簽名-只有用戶可以。 根據(jù)用例,您可以選擇其中一個(gè)。
現(xiàn)在,我不得不承認(rèn)我嘗試從密碼(RSA和ECDSA)派生非對(duì)稱密鑰對(duì)。 WebCrypto API不允許開(kāi)箱即用。 因此,我嘗試使用deriveBits()“生成”密鑰,例如,為RSA設(shè)置“ n”和“ d”值,為ECDSA設(shè)置x,y和d值( 可以在稍作搜索后在此處找到) 。 但是我失敗了–您不能僅將任何值指定為importKey參數(shù),并且約束條件未記錄在任何地方,除了底層算法細(xì)節(jié)外,這超出了我的實(shí)驗(yàn)范圍。
目的是,如果我們僅從密碼中獲取私鑰,就可以輕松地從私鑰中獲取公鑰(反之則不然)–然后我們存儲(chǔ)公鑰以進(jìn)行驗(yàn)證,而私鑰仍然是真正的私鑰,這樣我們就不能偽造簽名。
我必須在此處添加免責(zé)聲明,因?yàn)槲乙庾R(shí)到這不是很安全。 首先,在許多情況下從密碼派生密鑰是有問(wèn)題的。 但是,在這種情況下(放置簽名),可以。
附帶說(shuō)明–使用WebCrypto API十分繁瑣。 也許是因?yàn)檫€沒(méi)有人真正使用過(guò)它,所以搜索錯(cuò)誤基本上為您提供了Chromium的源代碼,而沒(méi)有其他任何東西。 感覺(jué)就像是一個(gè)未知的領(lǐng)域(盡管文檔和示例足以使您入門)。
我不知道以這種方式進(jìn)行電子簽名是否有用。 我將其實(shí)現(xiàn)為一個(gè)實(shí)際有意義的用例(參與方成員資格聲明簽名)。 它是否比畫(huà)布上的手繪簽名更好–我認(rèn)為是這樣(除非您從圖像中得出密鑰,否則,由于較高的熵,手寫(xiě)的密鑰會(huì)更好)。
翻譯自: https://www.javacodegeeks.com/2017/06/electronic-signature-using-webcrypto-api.html
總結(jié)
以上是生活随笔為你收集整理的使用WebCrypto API的电子签名的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spring javafx_带有Spri
- 下一篇: vivo WATCH 3 手表爆料:支持