使用 Golang 打造 Web 應用程式
  • Introduction
  • Go 環境配置
    • Go 安裝
    • GOPATH 與工作空間
    • Go 命令
    • Go 開發工具
    • 小結
  • Go 語言基礎
    • 你好,Go
    • Go 基礎
    • 流程和函式
    • struct
    • 物件導向
    • interface
    • 併發
    • 小結
  • Web 基礎
    • web 工作方式
    • Go 建立一個簡單的 web 服務
    • Go 如何使得 web 工作
    • Go 的 http 套件詳解
    • 小結
  • 表單
    • 處理表單的輸入
    • 驗證表單的輸入
    • 預防跨站指令碼
    • 防止多次提交表單
    • 處理檔案上傳
    • 小結
  • 存取資料庫
    • database/sql 介面
    • 使用 MySQL 資料庫
    • 使用 SQLite 資料庫
    • 使用 PostgreSQL 資料庫
    • 使用 beedb 函式庫進行 ORM 開發
    • NoSQL 資料庫操作
    • 小結
  • session 和資料儲存
    • session 和 cookie
    • Go 如何使用 session
    • session 儲存
    • 預防 session 劫持
    • 小結
  • 文字檔案處理
    • XML 處理
    • JSON 處理
    • 正則處理
    • 範本處理
    • 檔案操作
    • 字串處理
    • 小結
  • Web 服務
    • Socket 程式設計
    • WebSocket
    • REST
    • RPC
    • 小結
  • 安全與加密
    • 預防 CSRF 攻擊
    • 確保輸入過濾
    • 避免 XSS 攻擊
    • 避免 SQL 注入
    • 儲存密碼
    • 加密和解密資料
    • 小結
  • 國際化和本地化
    • 設定預設地區
    • 本地化資源
    • 國際化站點
    • 小結
  • 錯誤處理,除錯和測試
    • 錯誤處理
    • 使用 GDB 除錯
    • Go 怎麼寫測試案例
    • 小結
  • 部署與維護
    • 應用日誌
    • 網站錯誤處理
    • 應用部署
    • 備份和還原
    • 小結
  • 如何設計一個 Web 框架
    • 專案規劃
    • 自訂路由器設計
    • controller 設計
    • 日誌和配置設計
    • 實現部落格的增刪改
    • 小結
  • 擴充套件 Web 框架
    • 靜態檔案支援
    • Session 支援
    • 表單支援
    • 使用者認證
    • 多語言支援
    • pprof 支援
    • 小結
  • 參考資料
Powered by GitBook
On this page
  • 普通方案
  • 進階方案
  • 專家方案
  • 總結
  • links

Was this helpful?

  1. 安全與加密

儲存密碼

過去一段時間以來, 許多的網站遭遇使用者密碼資料洩露事件, 這其中包括頂級的網際網路企業–Linkedin, 國內諸如 CSDN,該事件橫掃整個國內網際網路,隨後又爆出多玩遊戲 800 萬用戶資料被洩露,另有傳言人人網、開心網、天涯社群、世紀佳緣、百合網等社群都有可能成為黑客下一個目標。層出不窮的類似事件給使用者的網上生活造成巨大的影響,人人自危,因為人們往往習慣在不同網站使用相同的密碼,所以一家“暴函式庫”,全部遭殃。

那麼我們作為一個 Web 應用開發者,在選擇密碼儲存方案時, 容易掉入哪些陷阱, 以及如何避免這些陷阱?

普通方案

目前用的最多的密碼儲存方案是將明文密碼做單向雜湊後儲存,單向雜湊演算法有一個特徵:無法透過雜湊後的摘要(digest)還原原始資料,這也是“單向”二字的來源。常用的單向雜湊演算法包括 SHA-256, SHA-1, MD5 等。

Go 語言對這三種加密演算法的實現如下所示:

//import "crypto/sha256"
h := sha256.New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))

//import "crypto/sha1"
h := sha1.New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))

//import "crypto/md5"
h := md5.New()
io.WriteString(h, "需要加密的密碼")
fmt.Printf("%x", h.Sum(nil))

單向雜湊有兩個特性:

  • 1)同一個密碼進行單向雜湊,得到的總是唯一確定的摘要。

  • 2)計算速度快。隨著技術進步,一秒鐘能夠完成數十億次單向雜湊計算。

結合上面兩個特點,考慮到多數人所使用的密碼為常見的組合,攻擊者可以將所有密碼的常見組合進行單向雜湊,得到一個摘要組合, 然後與資料庫中的摘要進行比對即可獲得對應的密碼。這個摘要組合也被稱為rainbow table。

因此透過單向加密之後儲存的資料,和明文儲存沒有多大區別。因此,一旦網站的資料庫洩露,所有使用者的密碼本身就大白於天下。

進階方案

透過上面介紹我們知道黑客可以用rainbow table來破解雜湊後的密碼,很大程度上是因為加密時使用的雜湊演算法是公開的。如果黑客不知道加密的雜湊演算法是什麼,那他也就無從下手了。

一個直接的解決辦法是,自己設計一個雜湊演算法。然而,一個好的雜湊演算法是很難設計的——既要避免碰撞,又不能有明顯的規律,做到這兩點要比想象中的要困難很多。因此實際應用中更多的是利用已有的雜湊演算法進行多次雜湊。

但是單純的多次雜湊,依然阻擋不住黑客。兩次 MD5、三次 MD5 之類別的方法,我們能想到,黑客自然也能想到。特別是對於一些開原始碼,這樣雜湊更是相當於直接把演算法告訴了黑客。

沒有攻不破的盾,但也沒有折不斷的矛。現在安全性比較好的網站,都會用一種叫做“加鹽”的方式來儲存密碼,也就是常說的 “salt”。他們通常的做法是,先將使用者輸入的密碼進行一次 MD5(或其它雜湊演算法)加密;將得到的 MD5 值前後加上一些只有管理員自己知道的隨機串,再進行一次 MD5 加密。這個隨機串中可以包括某些固定的串,也可以包括使用者名稱(用來保證每個使用者加密使用的金鑰都不一樣)。

//import "crypto/md5"
//假設使用者名稱 abc,密碼 123456

h := md5.New()
io.WriteString(h, "需要加密的密碼")

//pwmd5 等於 e10adc3949ba59abbe56e057f20f883e

pwmd5 :=fmt.Sprintf("%x", h.Sum(nil))

//指定兩個 salt: salt1 = @#$%   salt2 = ^&*()
salt1 := "@#$%"
salt2 := "^&*()"

//salt1+使用者名稱+salt2+MD5 拼接
io.WriteString(h, salt1)
io.WriteString(h, "abc")
io.WriteString(h, salt2)
io.WriteString(h, pwmd5)

last :=fmt.Sprintf("%x", h.Sum(nil))

在兩個 salt 沒有洩露的情況下,黑客如果拿到的是最後這個加密串,就幾乎不可能推算出原始的密碼是什麼了。

專家方案

上面的進階方案在幾年前也許是足夠安全的方案,因為攻擊者沒有足夠的資源建立這麼多的rainbow table。 但是,時至今日,因為平行計算能力的提升,這種攻擊已經完全可行。

怎麼解決這個問題呢?只要時間與資源允許,沒有破譯不了的密碼,所以方案是 : 故意增加密碼計算所需耗費的資源和時間,使得任何人都不可獲得足夠的資源建立所需的rainbow table。

這類別方案有一個特點,演算法中都有個因子,用於指明計算密碼摘要所需要的資源和時間,也就是計算強度。計算強度越大,攻擊者建立rainbow table越困難,以至於不可繼續。

這裡推薦 scrypt 方案,scrypt 是由著名的 FreeBSD 黑客 Colin Percival 為他的備份服務 Tarsnap 開發的。

dk := scrypt.Key([]byte("some password"), []byte(salt), 16384, 8, 1, 32)

透過上面的方法可以取得唯一的相應的密碼值,這是目前為止最難破解的。

總結

看到這裡,如果你產生了危機感,那麼就行動起來:

  • 1)如果你是普通使用者,那麼我們建議使用 LastPass 進行密碼儲存和產生,對不同的網站使用不同的密碼;

  • 2)如果你是開發人員, 那麼我們強烈建議你採用專家方案進行密碼儲存。

links

Previous避免 SQL 注入Next加密和解密資料

Last updated 4 years ago

Was this helpful?

目前 Go 語言裡面支援的函式庫

上一節:

下一節:

https://github.com/golang/crypto/tree/master/scrypt
目錄
確保輸入過濾
加密和解密資料