- 浏览: 149300 次
- 性别:
- 来自: 北京
文章分类
最新评论
我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。
加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。
这里的“佐料”被称作“Salt值”,这个值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。
下面详细介绍一下加Salt散列的过程。介绍之前先强调一点,前面说过,验证密码时要使用和最初散列密码时使用“相同的”佐料。所以Salt值是要存放在数据库里的。
用户注册时
用户输入【账号】和【密码】(以及其他用户信息);
系统为用户生成【Salt值】;
系统将【Salt值】和【用户密码】连接到一起;
对连接后的值进行散列,得到【Hash值】;
将【Hash值1】和【Salt值】分别放到数据库中。
用户登录时
用户输入【账号】和【密码】;
系统通过用户名找到与之对应的【Hash值】和【Salt值】;
系统将【Salt值】和【用户输入的密码】连接到一起;
对连接后的值进行散列,得到【Hash值2】(注意是即时运算出来的值);
比较【Hash值1】和【Hash值2】是否相等,相等则表示密码正确,否则表示密码错误。
有时候,为了减轻开发压力,程序员会统一使用一个salt值(储存在某个地方),而不是每个用户都生成私有的salt值。
----------------------------------
import java.security.MessageDigest;
public class PasswordEncoder {
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
private Object salt;
private String algorithm;
public PasswordEncoder(Object salt, String algorithm) {
this.salt = salt;
this.algorithm = algorithm;
}
public String encode(String rawPass) {
String result = null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
//加密后的字符串
result = byteArrayToHexString(md.digest(mergePasswordAndSalt(rawPass).getBytes("utf-8")));
} catch (Exception ex) {
}
return result;
}
public boolean isPasswordValid(String encPass, String rawPass) {
String pass1 = "" + encPass;
String pass2 = encode(rawPass);
return pass1.equals(pass2);
}
private String mergePasswordAndSalt(String password) {
if (password == null) {
password = "";
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt.toString() + "}";
}
}
/**
* 转换字节数组为16进制字串
* @param b 字节数组
* @return 16进制字串
*/
private static String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n = 256 + n;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static void main(String[] args) {
String salt = "helloworld";
PasswordEncoder encoderMd5 = new PasswordEncoder(salt, "MD5");
String encode = encoderMd5.encode("test");
System.out.println(encode);
boolean passwordValid = encoderMd5.isPasswordValid("1bd98ed329aebc7b2f89424b5a38926e", "test");
System.out.println(passwordValid);
PasswordEncoder encoderSha = new PasswordEncoder(salt, "SHA");
String pass2 = encoderSha.encode("test");
System.out.println(pass2);
boolean passwordValid2 = encoderSha.isPasswordValid("1bd98ed329aebc7b2f89424b5a38926e", "test");
System.out.println(passwordValid2);
}
}
http://blog.csdn.net/hexingzhi/article/details/7424872
http://zhanqi.net/blog/527/
加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。
这里的“佐料”被称作“Salt值”,这个值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。
下面详细介绍一下加Salt散列的过程。介绍之前先强调一点,前面说过,验证密码时要使用和最初散列密码时使用“相同的”佐料。所以Salt值是要存放在数据库里的。
用户注册时
用户输入【账号】和【密码】(以及其他用户信息);
系统为用户生成【Salt值】;
系统将【Salt值】和【用户密码】连接到一起;
对连接后的值进行散列,得到【Hash值】;
将【Hash值1】和【Salt值】分别放到数据库中。
用户登录时
用户输入【账号】和【密码】;
系统通过用户名找到与之对应的【Hash值】和【Salt值】;
系统将【Salt值】和【用户输入的密码】连接到一起;
对连接后的值进行散列,得到【Hash值2】(注意是即时运算出来的值);
比较【Hash值1】和【Hash值2】是否相等,相等则表示密码正确,否则表示密码错误。
有时候,为了减轻开发压力,程序员会统一使用一个salt值(储存在某个地方),而不是每个用户都生成私有的salt值。
----------------------------------
import java.security.MessageDigest;
public class PasswordEncoder {
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
private Object salt;
private String algorithm;
public PasswordEncoder(Object salt, String algorithm) {
this.salt = salt;
this.algorithm = algorithm;
}
public String encode(String rawPass) {
String result = null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
//加密后的字符串
result = byteArrayToHexString(md.digest(mergePasswordAndSalt(rawPass).getBytes("utf-8")));
} catch (Exception ex) {
}
return result;
}
public boolean isPasswordValid(String encPass, String rawPass) {
String pass1 = "" + encPass;
String pass2 = encode(rawPass);
return pass1.equals(pass2);
}
private String mergePasswordAndSalt(String password) {
if (password == null) {
password = "";
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt.toString() + "}";
}
}
/**
* 转换字节数组为16进制字串
* @param b 字节数组
* @return 16进制字串
*/
private static String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n = 256 + n;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static void main(String[] args) {
String salt = "helloworld";
PasswordEncoder encoderMd5 = new PasswordEncoder(salt, "MD5");
String encode = encoderMd5.encode("test");
System.out.println(encode);
boolean passwordValid = encoderMd5.isPasswordValid("1bd98ed329aebc7b2f89424b5a38926e", "test");
System.out.println(passwordValid);
PasswordEncoder encoderSha = new PasswordEncoder(salt, "SHA");
String pass2 = encoderSha.encode("test");
System.out.println(pass2);
boolean passwordValid2 = encoderSha.isPasswordValid("1bd98ed329aebc7b2f89424b5a38926e", "test");
System.out.println(passwordValid2);
}
}
http://blog.csdn.net/hexingzhi/article/details/7424872
http://zhanqi.net/blog/527/
发表评论
-
java -jar classpath心
2015-09-18 14:52 373http://sddhn.blog.163.com/blog/ ... -
split
2013-11-07 14:27 640split("\\+") -
cookie 和session 的区别
2013-04-01 14:18 668session是服务器端缓存 ... -
java SimpleDateFormat在多线程下问题
2013-02-26 17:43 1016https://github.com/dreamhead/u ... -
java 静态内部类
2012-11-30 17:57 717public class Outer { static int ... -
java 用户线程和守护线程
2012-11-09 17:26 844JVM会等待所有非守护线 ... -
Class.forName和ClassLoader.loadClass的区别
2012-11-05 15:39 595Class的装载分了三个阶段,loading,linking和 ... -
java里synchronized用法
2012-08-21 17:31 801http://blog.163.com/ray_jun/blo ... -
Java中的移位操作以及基本数据类型转换成字节数组【收集】
2012-03-09 10:43 1117http://blog.csdn.net/vozon/arti ... -
java移位操作
2012-02-28 16:03 4065---- http://jinguo.iteye.com/bl ... -
java 基本类型的相互转换
2012-02-28 14:06 3727int z=257; byte x=(byte)z; ... -
java并发
2011-06-30 10:12 646http://www.blogjava.net/xylz/ar ... -
struts2-标签中时间比较的方法
2011-04-19 12:33 984<s:iterator value="resu ... -
正则表达式
2011-04-12 16:24 670http://deerchao.net/tutorials/r ... -
struts2 s:iterator
2011-03-21 12:09 755<s:iterator value="user ...
相关推荐
对接接口时用到的一种常用加密算法,常用于验证签名,使用shiro-all-1.4.1.jar,可自行下载
总结,Java实现MD5加密算法主要是通过`java.security.MessageDigest`类,经过`getInstance("MD5")`获取MD5实例,然后使用`digest()`和`update()`方法处理数据,最终将二进制摘要转换为十六进制字符串。尽管MD5的安全...
MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,可以将任意长度的输入转化为固定长度的输出,通常用于数据校验和密码存储。...然而,考虑到MD5的安全性,现在更推荐使用如bcrypt或Argon2等现代哈希算法。
在提供的`MD5Code.java`文件中,应该包含了上述步骤的具体实现,通过阅读和理解这段代码,你可以更深入地了解如何在Java中应用MD5加密算法。不过,实际开发中,我们通常会使用现有的安全库,如Apache Commons Codec...
在Java编程语言中,MD5(Message-Digest Algorithm 5)是一种广泛使用的...现在更推荐使用如SHA-256或更强的加密算法。在实际应用中,通常会结合盐值(salt)和多次迭代(如bcrypt或scrypt)来提高密码存储的安全性。
下面将详细介绍Java中的MD5加密工具类及其使用方法。 MD5加密过程通常包括以下几个步骤: 1. **数据预处理**:将原始信息填充到固定长度,通常是512位的倍数。这通常通过在原始数据末尾添加0来实现,然后添加一个...
1. 引入库:Java标准库中已经包含了`java.security.MessageDigest`类,用于处理各种消息摘要算法,包括MD5。无需额外导入第三方库。 2. 创建MD5实例:首先需要创建一个`MessageDigest`实例,通过`getInstance()`...
Java MD5加密算法在Discuz用户表密码字段中的应用 MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,它能将任意长度的数据转换为固定长度的输出,通常是一个128位的二进制数,常以32位的十六进制形式...
以下是关于MD5加密算法及其在JSP中应用的详细知识点: 1. **MD5原理**: - MD5算法由Ronald Rivest在1991年设计,它将输入信息经过多次迭代运算后生成一个固定长度的摘要。这个摘要对输入信息极其敏感,微小的变动...
以下将详细介绍标题和描述中提到的Java加密算法,并结合给定的文件名,讨论具体实现。 1. **AES(Advanced Encryption Standard)**:高级加密标准,是一种对称加密算法,因其高效性和安全性被广泛应用。AESUtil....
在`www.pudn.com.txt`和`MD5加密程序java代码.txt`这两个文件中,可能包含有关MD5加密算法更详细的解释或者Java实现的代码示例,你可以查阅这些文件以获取更多信息。总的来说,理解MD5的工作原理和正确使用Java API...
需要注意的是,由于MD5的碰撞问题,现在在安全领域,MD5已经不被视为安全的加密算法,更推荐使用如SHA-256或更强的哈希函数。在处理敏感信息,尤其是用户密码时,通常会结合盐值(salt)和多次迭代来提高安全性,...
在Java中,我们可以使用`java.security.MessageDigest`类来实现MD5加密。以下是一个简单的MD5加密实例: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public ...
在提供的"MD5_JAVA加密"文件中,可能包含了一个完整的Java实现MD5加密功能的类或代码片段,供开发者直接在项目中使用。这个类可能包含了上述的所有步骤,简化了MD5加密的过程,使开发者能快速集成到自己的系统中,...
下面是一个简单的Java MD5加密的代码示例,对应于你提供的`TestMD5.java`文件: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class TestMD5 { public ...
在Java EE(J2EE)环境中,MD5加密通常结合各种框架如Struts、Spring和Hibernate来实现。Struts是MVC架构的Web开发框架,Spring提供了全面的DI(依赖注入)和AOP(面向切面编程)功能,而Hibernate则是一个流行的ORM...
总的来说,Java实现MD5加密是一个相对简单的过程,主要涉及到`MessageDigest`类的使用,通过调用其`getInstance()`方法获取MD5实例,然后对输入数据进行哈希处理,最后将结果转换为16进制字符串。在实际开发中,根据...
在实际应用中,为了提高安全性,通常会将MD5值与随机盐值结合,再进行加密,这样即使两个用户使用相同的密码,加密后的结果也会不同,增加了破解的难度。 `secr`可能是提供了一个加密后的密文或者是一个包含加密...
本篇文章将详细介绍Java中两种常见的密码加密算法:MD5(Message-Digest Algorithm 5)和SHA(Secure Hash Algorithm)。我们将通过`CodeUtil.java`这个代码文件来探讨如何在实际开发中实现这两种加密方式。 首先,...
为了增强安全性,这些敏感信息往往会被加密处理,MD5(Message-Digest Algorithm 5)就是一种常用的哈希加密算法。 MD5是一种广泛使用的加密散列函数,产生一个128位(16字节)的散列值,通常用32个十六进制数字...