基于密碼的身份認證包括了兩個部分:
- 伺服器端認證資訊的存儲
- 密碼的認證過程
基于密碼的身份認證有一個原則:僅使用人知道密碼。密碼不能被存儲在認證伺服器中,在認證過程中也不能通過網絡明文傳輸。因為存儲的資訊可能被竊取或者濫用,網絡可能被監聽。這些安全隐患都可能導緻密碼的洩露。下面我們看看MySQL是如何做密碼認證的。
MySQL中存儲的認證資訊
MySQL的mysql.user表中有password字段,其中存儲的資訊是用來做密碼認證的。當查詢這個字段時看到如下格式的字元串:
*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
這個字元是什麼呢?它是通過雜湊演算法SHA1計算出來的密碼的哈希值。SHA1的哈希值長20位元組,轉換成十六進制的字元串長40位元組。前面有一個固定的*總共占41位元組。這個哈希值是調用兩次SHA1雜湊演算法算出來的哈希值,代碼中稱為stage2hash。
stage2hash = sha1(sha1(密碼))
從stage2hash是無法推導出密碼的。即便這個哈希值被盜了,不知道使用者的密碼仍然無法認證成功。
MySQL的密碼認證過程
伺服器發送scramble到用戶端
當用戶端的連接配接初始化完成或者收到用戶端的COM_CHANGE_USER指令後,伺服器會發送一個随機的字元串給用戶端。這個随機的字元竄代碼中稱作scramble。它是用來産生一個一次性加密秘鑰的。
key = sha1(scramble|stage2hash)
用戶端和伺服器之間通過這個秘鑰來加密傳輸認證資訊。
用戶端發送加密的stage1hash到伺服器
用戶端将收到的scramble和stage2hash一起再次進行哈希,産生出的哈希值用作加密秘鑰。因為stage2hash并沒有在網絡上傳輸,隻有伺服器和用戶端知道,是以産生的秘鑰也隻有伺服器和用戶端知道。
接着将stage1hash加密後,發送給伺服器。stage1hash是将密碼用SHA1哈希一次後産生的哈希值。
stage1hash = sha1(密碼)
加密的算法很簡單,就是一個XOR操作。将key和stage1hash逐位元組做XOR的操作。
密文 = xor(key, stage1hash)
伺服器解密stage1hash,并檢查有效性
解密也很簡單,就是将密文與key做XOR操作。
stage1hash = xor(key, 密文)
接着通過stage1hash生成stage2hash
stage2hash = sha1(stage1hash)
然後将産生的stage2hash和mysql.user中存儲的哈希值進行比對,如果相同則認證成功,否則失敗。
MySQL的密碼認證的安全性
伺服器上的stage2hash被盜
由于盜取人不知道使用者密碼就無法産生正确的stage1hash,是以在伺服器比對stage2hash時會出錯。
網絡被監聽
通過網絡傳輸的隻有scramble随機字元串和加密的stage1hash。因為每次使用的秘鑰都不同,是以監聽者沒辦法擷取stage1hash或者利用這個加密的stage1hash進行認證。要想擷取到stage1hash,監聽者必須同時盜取了伺服器上存儲的stage2hash才行。本質上來說,伺服器認證的是stage1hash。如果攻擊者擷取了stage1hash,就如同擷取了使用者的密碼一樣。
本文轉自 lirulei90 51CTO部落格,原文連結:http://blog.51cto.com/lee90/1951587,如需轉載請自行聯系原作者