【问题标题】:MD5 algorithm to hash passwords with saltMD5算法用盐散列密码
【发布时间】:2016-11-03 22:58:19
【问题描述】:

为什么 getBytes[ ] 和 insert bytes[ ] 会给出不同的结果?

数据库:表定义

CREATE TABLE users (
  `username` VARCHAR(15),
  `password` VARCHAR(32),
  `salt`     VARCHAR(32)
);

每当我想创建一个新用户时,我都会生成一个随机盐(类型:字节[]),然后将它与其他列一起存储在数据库中。

但是,当我尝试使用 rs.getBytes("Salt") 从数据库中检索盐时,我不会得到相同的结果。

我知道我可以使用rs.getString("Salt") 检索盐,但我需要将其作为byte[] 类型获取。

我尝试将String 转换为Bytes[],但结果又不一样..!!

代码:插入数据库

String username = "admin";
String password = request.getParameter("password"); 
byte[] salt = SaltedMD5.getSalt(); 
password = SaltedMD5.getSecurePassword(password, salt); 
stmt.executeUpdate(String.format("INSERT INTO users VALUES('%s', '%s', '%s')", username, password, salt));

输出:查询结果

byte[] DB_salt = rs.getBytes("Salt");

【问题讨论】:

  • 你真的,真的需要了解prepared statements。您的查询插入一个字节数组的 toString 表示,它总是看起来像 [B@12435,即类型后跟一个 hashCode。此外,不要将字节存储在 varchar 列中。要么使用二进制类型,要么使用 base64 将字节数组转换为可打印的字符串。
  • 请忘记 MD5 散列密码,它太快了,很容易被暴力破解 (100 Giga MD5 per second)。而是切换到 BCrypt 或 PBKDF2。
  • 准备好的语句似乎没有帮助..我应该使用 rs.getBytes("Salt") 从数据库中获取盐吗?
  • 如果我将盐存储为 String 它可以工作,但我无法将 byte[ ] 转换为 String 。有什么想法吗??

标签: java mysql hash md5 salt


【解决方案1】:

帮自己一个忙,改用安全算法。不仅您的密码会得到妥善保护,而且您也不必关心盐的生成和存储。

大多数BCrypt 实现将生成的盐作为结果哈希的一部分包含在内,因此您只需要一个最小长度为varchar(60) 的密码哈希字段。

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
String hashToStoreInDb = BCrypt.hashpw(password, BCrypt.gensalt());

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from existingHashFromDb.
Boolean isPasswordCorrect = BCrypt.checkpw(password, existingHashFromDb);

【讨论】: