对于此次泄露门事件,由于本人的帐号(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(); } }