華文網

HTTP有辦法實現相對安全的通信嗎?

估計很多隻愛看標題不愛看內容的人會立馬想噴。“都什麼年代了,https都爆出很多漏洞,更何況是http?”雖然小編很菜,但這個簡單的道理還是略知一二的,所以標題中也加了“相對”二字。

之所以探討這個話題,是因為目前仍有較多網站使用的是http,而且有些環境下,也未必非要整站走https,例如一些單位的內部網站,因為完全隔離了外部網路,各種攻擊的風險會大幅降低,所以通常只需要對密碼輸入等關鍵環節做好保護即可。而且https在帶來更高安全性的同時,也是要以犧牲性能為代價的,雖然隨著硬體的提速這種影響已經越來越小,但對於大型的應用系統,
這還是不得不考慮的。例如像政府部門內部使用的系統,由於要承載的業務量很大,其中還涉及到電子影像傳輸等高能耗業務,如果每次請求的處理速度慢0.1秒,那麼對於整個系統的行政效率就會帶來較大的影響。而我們可以看到,就算是個人郵箱等私密性較高的應用場景,也通常只是在登錄環節走https,之後則改為http。

在大多數場景中,如何防止系統資料被非法篡改,比防止資料被偵聽會顯得更加重要。

而資料之所以被篡改,大多數情況下並不是駭客用什麼複雜的技術去非法入侵伺服器,而是最簡單粗暴的方式,用你的密碼登錄系統然後進行操作。如去年報導的高考志願被修改事件,就是甲考生用乙考生的帳號密碼登錄系統進行修改的。也就是說,密碼保護是最為關鍵的。而相對於https,http最大的問題是在傳輸的時候資料完全處於“果奔”狀態,
有心人只要做一個偽基站之類,就可以攔截下你的資料,進而輕易獲取密碼。

在繼續討論之前,我們先看一下https的驗證過程:

圖中可以看到,在用戶端請求時,伺服器端會生成私密金鑰和公開金鑰,然後公開金鑰會返回給用戶端,用戶端再通過公開金鑰來加密一個隨機碼併發送給伺服器,

伺服器端用私密金鑰解密取得隨機碼。接著使用該隨機碼作為金鑰來對資料進行對稱加密解密。細心的朋友可能發現,這個過程其實是有漏洞的,就是在圖中的第3步公開金鑰下發給用戶端的環節,如果中途加了一個中間人,偽造一套公開金鑰和私密金鑰,然後將公開金鑰返回給用戶端,用戶端用該公開金鑰加密密碼,
中間人就可以通過私密金鑰解密來取得密碼。所以,https真正實現的過程會比圖中複雜得多,還要借助憑證授權來對公開金鑰進行簽名。而http雖然也可以用各種對稱、非對稱加密,但由於缺乏了最後一環,因此是無法真正保證資料傳輸的安全的。

雖然無法做到https那樣的安全性,但借助線下密碼加線上密碼相結合的方式,還是能夠一定程度上提升安全性的。過程大概是這樣的:

圖中我們其實是用到了兩個密碼,口令A是只有使用者和伺服器知道的密碼,這個密碼主要用來加密和解密公開金鑰的,而另外使用者還有一個登陸密碼。在現實場景中,這是可以實現的。例如,群眾甲到前臺申請開通網上辦事功能的時候,前臺操作人在系統中隨機生成一個口令A及一個登陸密碼,然後列印或者發送一條手機短信給群眾甲。還可以指定口令的有效時間。群眾甲回到家裡,在首次登錄的時候要輸入口令A來解密公開金鑰,然後輸入使用者密碼並用公開金鑰進行加密,這個過程是在用戶端完成的(可通過JS實現)。登錄成功後,強制要求其修改口令A,這個過程同樣涉及到公開金鑰傳輸的加密的問題,可以繼續用口令A來進行對稱加密加密,修改完成後就可以用口令B取代之前的口令A了。這種方式基本上能夠保障使用者密碼傳輸的安全性,只是需要使用者輸入兩個密碼,會對使用者體驗有較大的影響,有點多此一舉的感覺。可以考慮將口令保存在本地Cookie來減少使用者輸入的步驟,只是這又涉及到安全性的問題了,需要根據實際情況衡量。在具體實現上,前端可以用jsencrypt(實現RSA加密)結合crypto-js(實現AES/SHA解密),後端則根據不同的程式設計語言選擇對應的演算法即可。類似的代碼網上有很多,就不粘出來了。

上述的方法只適用於登錄等少數環節的加密解密,只是一種基於http環境下的相對安全的實現方式,要真正提升安全,建議還是儘量上https吧,簡單省事,目前有免費的證書,收費的也已經比以前下降了很多。

圖中我們其實是用到了兩個密碼,口令A是只有使用者和伺服器知道的密碼,這個密碼主要用來加密和解密公開金鑰的,而另外使用者還有一個登陸密碼。在現實場景中,這是可以實現的。例如,群眾甲到前臺申請開通網上辦事功能的時候,前臺操作人在系統中隨機生成一個口令A及一個登陸密碼,然後列印或者發送一條手機短信給群眾甲。還可以指定口令的有效時間。群眾甲回到家裡,在首次登錄的時候要輸入口令A來解密公開金鑰,然後輸入使用者密碼並用公開金鑰進行加密,這個過程是在用戶端完成的(可通過JS實現)。登錄成功後,強制要求其修改口令A,這個過程同樣涉及到公開金鑰傳輸的加密的問題,可以繼續用口令A來進行對稱加密加密,修改完成後就可以用口令B取代之前的口令A了。這種方式基本上能夠保障使用者密碼傳輸的安全性,只是需要使用者輸入兩個密碼,會對使用者體驗有較大的影響,有點多此一舉的感覺。可以考慮將口令保存在本地Cookie來減少使用者輸入的步驟,只是這又涉及到安全性的問題了,需要根據實際情況衡量。在具體實現上,前端可以用jsencrypt(實現RSA加密)結合crypto-js(實現AES/SHA解密),後端則根據不同的程式設計語言選擇對應的演算法即可。類似的代碼網上有很多,就不粘出來了。

上述的方法只適用於登錄等少數環節的加密解密,只是一種基於http環境下的相對安全的實現方式,要真正提升安全,建議還是儘量上https吧,簡單省事,目前有免費的證書,收費的也已經比以前下降了很多。