這段時間有一個對web app進行簽名驗證的一個需求,爲了確保所下載的apk包來自於咱們所信任的服務器,防止請求被劫持或者替換,因爲暫時仍是使用http協議在上https以前有一個過渡期,因此不得不考慮傳輸安全,畢竟http就是在整個網絡上"裸奔"。前端
作這個以前咱們首先得了解數字簽名究竟是什麼,在作這個驗籤以前我也一直是處於據說過的狀態中,因此作這個任務以前花了一點時間去了解一下。簡單說數字簽名只作一件事情,就是證實這個內容必定來自於某人,爲何呢?由於使用私鑰進行簽名,所以只有他本身能生成本身的簽名(私鑰被盜不算)。git
說這個數字簽名以前咱們首先簡單提一下密碼學的知識,加密方法大體分爲兩類:對稱加密(加密和解密都使用一套密鑰)、非對稱加密(有兩套密鑰,一套私鑰、一套公鑰,私鑰只有本身知道,公鑰能夠給其餘人;通常發送方用公鑰加密發送消息,而只有本身可以用私鑰進行解密,以此達到安全傳輸消息的目的;而簽名通常使用私鑰,用公鑰進行驗證簽名)。可是我在實現個人過程當中發現了一個問題,網上大部分講解數字簽名的文章好像和真正的簽名算法有所出入,最後在前組長以及查看《密碼編碼學與網絡安全》數字簽名這一章才讓我有點清晰。web
網上的資料關於數字簽名的流程主要爲:服務器將內容進行hash獲得內容的摘要,而後使用私鑰加上摘要完成簽名,而後將內容以及簽名一塊兒發給接收方,接收方收到以後使用服務器的公鑰進行解密獲得摘要一,而後再使用和服務器同樣的hash算法對內容進行hash獲得摘要二,而後對比兩個摘要是否相等,若是相等就說明簽名經過,不相等就驗籤失敗。算法
帶着認識開始作簽名任務,發如今和後臺對接的時候有點小差異,我理解的是要解密對比摘要,很後臺說的驗簽有點出入(內容hash+公鑰+簽名代入簽名驗證算法)得出結果?最後查了一下資料發現數字簽名的通常模型爲:後端
根據這個模型來看,第一部分理解都是沒有問題的,可是問題就是處在驗簽過程,圖上是直接使用使用內容hash+簽名代入簽名驗證算法得出結果,和後臺理解的完美貼合。看到這裏我就更加疑惑了,難道網上的資料都有問題?並且維基給出來的數字簽名原理和我之前理解的同樣,以下圖:安全
第一部分和上圖的過程一摸同樣,惟一的區別就是驗簽過程。出於找到緣由的目的繼續在《密碼編碼學與網絡安全》這本書中尋找緣由,最終找到了影子:服務器
RSA方法:hash函數的輸入是要簽名的消息,輸出是定長的hash碼(前H),用發送發的私鑰(PRa)將該Hash碼加密造成簽名,而後發送消息及其簽名。接收方收到消息後計算hash碼(後H),而且使用發送方的公鑰對簽名解密,若是計算出的Hash碼與解密出結果相同,則認爲簽名是有效的。由於只有發送方擁有私鑰,因此只有發送方可以產生有效的私鑰。 DSA方法:DSA採用hash函數,獲得hash碼,它以hash碼和爲這次簽名產生的隨機數(k)做爲簽名函數的輸入,簽名函數依賴於發送發的私鑰(PRa)和一組參數,這一組參數爲通訊夥伴共有,能夠認爲這組參數構成全局公鑰(PUG)。接受方,對接收到的消息產生hash,這個hash碼和簽名一塊兒做爲驗證函數的輸入,驗證函數依賴於全局公鑰和發送方公鑰(PUa)。若驗證函數的輸出等於r成分則簽名有效。網絡
最後個人理解是:數字簽名的模型是上圖13.1這樣的,可是在實現方式上是能夠調整,所以網上的大部分資料應該都是相對於某一種簽名方式來講的,而不是對簽名過程進行分析。app
這裏我只說前端方向,在這個任務中我採用的就是通常模型的基本流程,先生成一套RSA公私鑰,前端直接將公鑰硬編碼。後端讀取apk(buffer讀取)並將內容進行hash(先後端協商使用sha256),依賴發送方的私鑰將hash碼代入簽名函數,獲得簽名;把apk和簽名一塊兒發給前端,前端首先下載apk,而後讀取apk文件(前端讀取能夠文本形式、dataurl形式、ArrayBuffer形式),先後端讀取形式不一樣驗籤必定失敗,因爲後臺使用的是buffer讀取,所以前端也只能採用buffer讀取。⚠️(crypto-js中sha256不支持原生的ArrayBuffer,最後選擇js-sha256,簽名驗證庫:jsencrypt,除了文檔不太友好以外都挺不錯,自帶一個測試demo)。文件讀取方式統不統一就決定了這次簽名能不能成功。svg
以上都是我的理解,若有錯誤,還得麻煩各位大佬指出來。