在Java中加密和解密密码

41

我想在Java中加密和解密密码,并以加密形式存储到数据库中。如果这是开源的,那就太好了。有任何建议/指针吗?


1
唯一的建议是不要使用加密。使用哈希...可以加一些盐。 - Nishant
@Nishant:你有没有任何例子,这样我就可以更好地理解。 - Raje
使用http://www.mindrot.org/projects/jBCrypt/来完成此任务。 - Aaron Digulla
请参见 [tag:password-encryption] 了解原因。 - user207421
5个回答

20

这是我使用的MD5加密算法,它会返回加密后的结果。

   public class CryptWithMD5 {
   private static MessageDigest md;

   public static String cryptWithMD5(String pass){
    try {
        md = MessageDigest.getInstance("MD5");
        byte[] passBytes = pass.getBytes();
        md.reset();
        byte[] digested = md.digest(passBytes);
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<digested.length;i++){
            sb.append(Integer.toHexString(0xff & digested[i]));
        }
        return sb.toString();
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(CryptWithMD5.class.getName()).log(Level.SEVERE, null, ex);
    }
        return null;


   }
}

你无法解密MD5,但可以比较其输出,因为如果你将相同的字符串放入此方法中,它将具有相同的加密输出。如果你想解密,需要使用SHA。你永远不会对用户密码使用解密。始终使用MD5。该例外情况实际上是多余的,它永远不会被抛出。


我不知道为什么,但这个算法对我来说没有100%的效果。有时结果是不正确的(我将结果与Tomcat上的JDBC领域返回的MD5加密密码进行了比较)。这个对我完美地起作用:http://www.java2s.com/Code/Java/Security/UseMD5toencryptastring.htm - Xithias
1
@AdrianStamin 你能解释一下 0xff & digested[i] 的作用吗? :) - theapache64
3
MD5不安全(容易被解密),绝不应该用于密码。 - alttag
1
digested[i] & 0xff 确保了 digested[i] 的八个最低有效位可以是非零的。 0xff 在十进制中为 255,在二进制中为 00000000 00000000 00000000 11111111。 当你对任何字节进行按位操作 AND (&) 时,它将确保结果数字中只有最不重要的位可以是非零的。 例如: 00000000 00000000 00000000 11111111 (255) & 00000000 00011111 00000000 01000000 (8000) => 00000000 00000000 00000000 01000000 - Adrian Stamin
1
@alttag 你说得对。MD5已经不安全了。现在人们使用加盐的MD5。存储密码的最佳方式是让其他人来做。比如Facebook或Yahoo :) - Adrian Stamin
1
@AdrianStamin:即使是加盐的MD5也不是一个好主意。加盐是好的,但是用破损的哈希进行加盐仍然是有问题的。 - alttag

10

编辑:此答案较旧。现在不鼓励使用MD5,因为可以轻易地被破解。


我想对您来说,MD5应该足够好了吧?您可以使用MessageDigest来实现。

MessageDigest.getInstance("MD5");

这里还列出了其他算法,点击此处查看。

如果您真的想要,以下是其第三方版本:Fast MD5


51
MD5是单向哈希函数,只能加密,无法解密。 - Kal
5
+1. @avs31586,你其实不需要解密密码。相反,你可以用MD5加密,然后在验证时始终比对两个MD5值。这样就可以避免人们猜测你的加密算法所带来的问题了。 - griegs
9
我知道这个问题很老,但请永远不要使用MD5来“加密”密码。MD5不安全,很容易被解密。 - alttag
正如Kal已经说过的那样,问题是要加密和解密密码。MD5只是其中一种方式->哈希。 - Anton
1
MD5自2009年以来已经被破解:http://cryptocrats.com/crypto/md5-the-hash-algorithm-is-now-broken/ - tgr
显示剩余3条评论

8

Jasypt 可以轻松简单地完成这项任务。


1
我现在正在处理类似的事情...因为听起来你确实需要在某个时候解密密码,所以像MD5这样的东西是行不通的。我认为这是最简单的解决方案。 - JasonStoltz
@JasonStoltz 如何在 Jasypt 中添加盐? - kittu

2

1
你的示例很棒,但是它没有提供解密功能。你有解密的任何想法吗? - Raje
使用Base64Decoder 例子在这里 - raksja
org.apache.commons.codec.binary.Base64需要哪个包? - Raje
我建议的是一种非常简单的方法。但是sun打包文件严格来说是不可用的。 String encoded = (new BASE64Encoder()).encode("text to be encoded".getBytes("UTF-8")); byte decodedRaw[] = (new BASE64Decoder()).decodeBuffer(encoded); String decoded = new String(decodedRaw, "UTF8");如果您想采用另一种方法,可以参考这个并创建自定义加密器/解密器。 - raksja
5
Base64编码与加密和解密有什么关系?没有。 - user207421
7
Base64编码不是加密,任何存储在Base64中的内容都很容易被知道,其中没有保护措施。你们中有在银行或金融机构工作的吗?天哪,希望没有! - chubbsondubs

2
我最近使用了Spring Security 3.0(顺便提一下,与Wicket结合使用),非常满意。这里有一个很好的全面教程文档。还可以看一下这个教程,它对Spring Security 2的哈希/盐/解码设置进行了很好的解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接