對於此次泄露門事件,由於本人的帳號(CSDN)有在內因此很想說shit…同時以爲csdn真丟臉… php
一直想不到csdn會用明文保存密碼,上次忘記密碼郵箱直接收到了密碼的網站大概在是十年前的某註冊用戶不到十個的小網站吧. java
回到重點,咱們知道,若是直接對密碼進行散列,那麼黑客能夠對經過得到這個密碼散列值,而後經過查散列值字典(例如MD5密碼破解網站),獲得某用戶的密碼。 程序員
加Salt能夠必定程度上解決這一問題。所謂加Salt方法,就是加點「佐料」。其基本想法是這樣的:當用戶首次提供密碼時(一般是註冊時),由系統自動往這個密碼裏撒一些「佐料」,而後再散列。而當用戶登陸時,系統爲用戶提供的代碼撒上一樣的「佐料」,而後散列,再比較散列值,已肯定密碼是否正確。 算法
這裏的「佐料」被稱做「Salt值」,這個值是由系統隨機生成的,而且只有系統知道。這樣,即使兩個用戶使用了同一個密碼,因爲系統爲它們生成的salt值不一樣,他們的散列值也是不一樣的。即使黑客能夠經過本身的密碼和本身生成的散列值來找具備特定密碼的用戶,但這個概率過小了(密碼和salt值都得和黑客使用的同樣才行)。 數據庫
下面以PHP示例,講解md5($pass.$salt)加密函數。 數組
<?php function hash($a) { $salt=」Random_KUGBJVY」; //定義一個salt值,程序員規定下來的隨機字符串 $b=$a.$salt; //把密碼和salt鏈接 $b=md5($b); //執行MD5散列 return $b; //返回散列 } ?>
調用方式:$new_password=hash($_POST[password]); //這裏接受表單提交值,並進行加密 dom
下面詳細介紹一下加Salt散列的過程。介紹以前先強調一點,前面說過,驗證密碼時要使用和最初散列密碼時使用「相同的」佐料。因此Salt值是要存放在數據庫裏的。 函數
用戶註冊時, 網站
用戶登陸時, 加密
有時候,爲了減輕開發壓力,程序員會統一使用一個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(); } }