使用java加密和解密密码使用啥API和算法

Posted

技术标签:

【中文标题】使用java加密和解密密码使用啥API和算法【英文标题】:What API and algorithm to be used to encrypt and decrypt a password using java使用java加密和解密密码使用什么API和算法 【发布时间】:2012-12-12 02:16:33 【问题描述】:

我目前正在使用 Java 创建应用程序,我在谷歌上搜索了 Java 密码加密,但结果如此巨大,我感到不知所措。如何使用 Java 加密和解密密码?加密和解密密码的最佳实践是什么?我猜 MD5 不是一种方法,因为它是一种单向哈希。我使用 struts2 作为我的框架,想知道他们是否提供密码加密

【问题讨论】:

我强烈建议您使用单向哈希算法,而不是可以解密的。由于各种安全原因,一种方式的哈希是最好的。 您不会加密和解密密码,因为它是双向的。你会对它们加盐和散列,正是因为它是单向的,因此没有人可以通过散列密码回到原始密码。使用bcrypt。 您真的需要加密密码吗?在您的场景中不可能散列?你的钥匙从哪里来?用户输入的主密码? MD5 不是一个安全的单向哈希 (en.wikipedia.org/wiki/MD5) @MrSmith42 MD5 的单向性(第一个原像)还是相当强的。冲突很弱,但不适用于密码散列。虽然最好使用其他东西,但 MD5 的加密弱点并不是密码散列的直接关注点。选择一个好的强化方案比选择 SHA-2 而不是 MD5 重要得多。 【参考方案1】:

对我来说,我认为 MD5 是最好的方法,如果用户忘记密码,您不需要解密密码,您可以给他一种生成新密码的方法,并且登录时您可以比较数据库中存在的哈希值和用户输入的哈希值

【讨论】:

MD5 不是最好的方法。实际上,MD5 不应再用于散列密码。请改用更强的哈希算法。 你只是说MD5不是最好的方法,你没有给出解决方案?? @haffanehatim 因为这个问题已经讨论到死了。与往常一样,使用 bcrypt、scrypt 或 PBKDF2 以及每个用户唯一的 salt。不应直接使用通用哈希(包括 MD5 和 SHA-2)对密码进行哈希处理。 @haffanehatim 他正在评论您的答案,而不是提供他自己的答案。他的评论是正确的。没有必要自己下一个鸡蛋来检测别人下的烂鸡蛋。【参考方案2】:

始终使用 单向哈希算法。

我会说 GO 与 MD5 散列。在数据库中存储密码时,使用 MD5 散列。因此,如果您的密码为 pass,经过哈希处理后,它将被存储为 asjasdfklasdjf789asdfalsdfashdflasdf(32 个字符)。

正如你所说,你也想解密密码。 我会说不要这样做。在对照数据库检查密码时,您可以做的是散列密码并将该字符串与您在数据库中的字符串进行比较。

if (DoHashMD5(myPass).equals(rs.getString(2))) 
    System.out.print("You are registered user!!!");
 else 
    System.out.print("Invalid user!!!");

这里rs.getString(2) 将是您的查询参数。

【讨论】:

没有盐的单向哈希非常不安全,因为容易受到彩虹表攻击。 @JBNizet :我同意某些观点,但我想说,哈希本身甚至不安全。看看my question @FahimParkar:呃,这正是我要说的:没有盐的哈希是非常不安全的。这就是我推荐 bcrypt 的原因。【参考方案3】:

另外我不推荐使用 MD5,因为它已经坏了。而不是你可以使用 SHA512 它是安全的散列方法,你可以使用MessageDigest。下面是我在我的一个项目中使用的代码,效果很好

public String encode(String password, String saltKey)
        throws NoSuchAlgorithmException, IOException 

    String encodedPassword = null;
    byte[] salt = base64ToByte(saltKey);

    MessageDigest digest = MessageDigest.getInstance("SHA-512");
    digest.reset();
    digest.update(salt);

    byte[] btPass = digest.digest(password.getBytes("UTF-8"));
    for (int i = 0; i < ITERATION_COUNT; i++) 
        digest.reset();
        btPass = digest.digest(btPass);
    

    encodedPassword = byteToBase64(btPass);
    return encodedPassword;


private byte[] base64ToByte(String str) throws IOException 
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] returnbyteArray = decoder.decodeBuffer(str);
    if (log.isDebugEnabled()) 
        log.debug("base64ToByte(String) - end");
    
    return returnbyteArray;

【讨论】:

不安全:你没有给密码加盐,而且有问题:你依赖于默认的平台编码。 有什么理由在 PBKDF2 或 bcrypt 上使用自制迭代方案? - 另一个问题是您的代码非常不完整。例如,它不显示盐的创建或验证的工作方式。 @CodesInChaos..salt 创建是 OP 试图解决的问题类型所独有的,他/她可以根据自己的喜好生成 salt,这就是我没有展示的原因 从加盐密码中,我如何将其与用户输入进行比较?我必须再次加密吗?请提供盐样品。 @user962206 这是一个常数,至少应该是 10000。如果你能承受更高的计算量,甚至更大。【参考方案4】:

更新

试试 JBCrypt:

String password = "MyPassword123";
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));
System.out.println(hashed);  // $2a$12$QBx3/kI1SAfwBDFOJK1xNOXK8R2yC7vt2yeIYusaqOisYbxTNFiMy

下载jBCrypt-0.3 from here,查看README文件了解更多详情。

【讨论】:

新代码可能会让读者误以为恒定值是好盐(一种常见的误解),所以除非你用一个像样的盐生成代码替换它,否则我不会撤销我的反对票。而且您仍在使用快速哈希,这本身就值得反对。 @CodesInChaos:快速哈希是什么意思? 任何具有单次迭代的通用哈希(MD5、SHA-x、...)都太快了。您应该故意使用昂贵的结构,例如 bcrypt、scrypt 或至少 PBKDF2。 感谢@CodesInChaos,这是一堂 gr8 课。我还在hacker news 上找到了一个有趣的帖子 在 scrypt、bcrypt 和 PBKDF2 之间进行选择取决于具体情况,但它们都比大多数自制解决方案要好得多。你的新 bcrypt 代码看起来不错。【参考方案5】:

有一个很好的项目致力于用 Java 解决这个问题。 本质上,它提供了两种加密用户密码的方法: - MD5 - SHA1

看一下链接: jasypt

【讨论】:

这比只回答链接更糟糕,因为你的摘要写得很糟糕。 您可能还想用一些更好的术语来更新您的答案。散列!=加密;加密是可逆的。【参考方案6】:

好吧,据我所知,我们有一些算法来保护密码。

    MD5 - PBKDF2 - SHA - BCrypt 和 SCrypt -

其中 BCrypt 和 SCrypt 是更安全的密码安全方式。

【讨论】:

以上是关于使用java加密和解密密码使用啥API和算法的主要内容,如果未能解决你的问题,请参考以下文章

JAVA使用DES加密解密

java des 默认采用啥加密模式

delphi 数字加密和解密算法

AES加密和解密Java

Java 加密解密的方法有哪些

非对称加密中,公钥在啥情况下用于加密,啥情况用于解密?