對於這次泄露門事件,因為本人的帳號(CSDN)有在內所以很想說shit…同時覺得csdn真丟臉…
一直想不到csdn會用明文儲存密碼,上次忘記密碼郵箱直接收到了密碼的網站大概在是十年前的某註冊使用者不到十個的小網站吧.
回到重點,我們知道,如果直接對密碼進行散列,那麼駭客可以對通過獲得這個密碼散列值,然後通過查散列值字典(例如MD5密碼破解網站),得到某使用者的密碼。
加Salt可以一定程度上解決這一問題。所謂加Salt方法,就是加點“佐料”。其基本想法是這樣的:當使用者首次提供密碼時(通常是註冊時),由系統自動往這個密碼裡撒一些“佐料”,然後再散列。而當使用者登入時,系統為使用者提供的代碼撒上同樣的“佐料”,然後散列,再比較散列值,已確定密碼是否正確。
這裡的“佐料”被稱作“Salt值”,這個值是由系統隨機產生的,並且只有系統知道。這樣,即便兩個使用者使用了同一個密碼,由於系統為它們產生的salt值不同,他們的散列值也是不同的。即便駭客可以通過自己的密碼和自己產生的散列值來找具有特定密碼的使用者,但這個幾率太小了(密碼和salt值都得和駭客使用的一樣才行)。
下面以PHP樣本,講解md5($pass.$salt)加密函數。
<?phpfunction hash($a) {$salt=”Random_KUGBJVY”; //定義一個salt值,程式員規定下來的隨機字串$b=$a.$salt; //把密碼和salt串連$b=md5($b); //執行MD5散列return $b; //返回散列}?>
調用方式:$new_password=hash($_POST[password]); //這裡接受表單提交值,並進行加密
下面詳細介紹一下加Salt散列的過程。介紹之前先強調一點,前面說過,驗證密碼時要使用和最初散列密碼時使用“相同的”佐料。所以Salt值是要存放在資料庫裡的。
使用者註冊時,
- 使用者輸入【帳號】和【密碼】(以及其他使用者資訊);
- 系統為使用者產生【Salt值】;
- 系統將【Salt值】和【使用者密碼】串連到一起;
- 對串連後的值進行散列,得到【Hash值】;
- 將【Hash值1】和【Salt值】分別放到資料庫中。
使用者登入時,
- 使用者輸入【帳號】和【密碼】;
- 系統通過使用者名稱找到與之對應的【Hash值】和【Salt值】;
- 系統將【Salt值】和【使用者輸入的密碼】串連到一起;
- 對串連後的值進行散列,得到【Hash值2】(注意是即時運算出來的值);
- 比較【Hash值1】和【Hash值2】是否相等,相等則表示密碼正確,否則表示密碼錯誤。
有時候,為了減輕開發壓力,程式員會統一使用一個salt值(儲存在某個地方),而不是每個使用者都產生私人的salt值。
以上內容出自:http://blog.csdn.net/blade2001/article/details/6341078
上面講了php的基本實現
看看Java ,講的很詳細
(1)讀入帳號口令String name=args[0];String passwd=args[1];分析:這裡為了簡便而通過命令列讀入帳號和口令,實際程式中可以製作圖形介面供使用者輸入。(2)產生隨機數(鹽)Random rand = new Random();byte[] salt = new byte[12];rand.nextBytes(salt);分析:建立位元組數組salt。使用Java中Random類產生隨機數,執行Random類的nextBytes()方法,方法的參數為salt,即可產生的隨機數並將隨機數賦值給salt。
(3)產生MessageDigest對象
MessageDigest m=MessageDigest.getInstance(“MD5″);
分析:執行MessageDigest類的靜態方法getInstance()產生MessageDigest對象。其中傳入的參數指定計算訊息摘要所使用的演算法。
(4)傳入鹽和需要計算的位元組數組
m.update(salt);
m.update(passwd.getBytes(“UTF8″));
分析:將第2步的鹽和第1步的口令分別傳遞給MessageDigest對象的update( )方法。
(5)計算訊息摘要
byte s[]=m.digest();
分析:執行MessageDigest對象的digest()方法完成計算,計算的結果通過位元組類型的數組返回。
(6)在檔案中或資料庫中儲存帳號和口令的訊息摘要
PrintWriter out= new PrintWriter(new FileOutputStream(“passwdsalt.txt”));
out.println(name);
for(int i=0;i<salt.length;i++){
out.print(salt[i]+ “,”);
}
out.println(“”);
out.println(result);
分析:這裡將帳號、鹽和口令訊息摘要報存在passwd.txt檔案中。對於鹽,這裡將數組中各個byte值以數字儲存在檔案中,各個數字之間以逗號隔開,這樣比較直觀,實際使用時可直接將位元組數組以二進位儲存。
具體實現
import java.util.*;import java.io.*;import java.security.*;public class SetPassSalt {public static void main(String args[]) throws Exception {// 讀入帳號口令String name = "lbwleon.info";String passwd = "lbwleon.info";// 產生鹽Random rand = new Random();byte[] salt = new byte[12];rand.nextBytes(salt);// 計算訊息摘要MessageDigest m = MessageDigest.getInstance("MD5");m.update(salt);m.update(passwd.getBytes("UTF8"));byte s[] = m.digest();String result = "";for (int i = 0; i < s.length; i++) {result += Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);}// 儲存帳號、鹽和訊息摘要PrintWriter out = new PrintWriter(new FileOutputStream("d:/passwdsalt.txt"));out.println(name);for (int i = 0; i < salt.length; i++) {out.print(salt[i] + ",");}out.println("");out.println(result);out.close();}}