【问题标题】:ruby: create MD5 checksum with salt?ruby:用盐创建 MD5 校验和?
【发布时间】:2021-04-03 15:55:54
【问题描述】:

我正在尝试使用盐在ruby 中创建MD5 校验和,但我找不到使用标准digest/md5 包的任何方法。

我知道我能做到:

require 'digest/md5'
checksum = '$1$' + (Digest::MD5.new << plaintext).to_s

但是,似乎没有任何方法可以使用digest 为这个MD5 校验和生成指定盐,而且我还没有在ruby 中找到可以用于此的任何其他包。

这在ruby 中是否可行?

提前谢谢你。

【问题讨论】:

  • 你能添加一些示例输入和预期的输出吗?
  • 纯文本 => hippo, salt => q2w3e4, 预期结果:$1$q2w3e4$WzKE5mnfb45yU6XNRLNJQ0

标签: ruby hash md5 checksum salt


【解决方案1】:

使用 Salt 创建/验证 *nix 样式的 MD5 条目

如果您尝试管理 *nix 系统密码,最好只使用系统实用程序而不是自己构建。但是,如果您想仅使用 Ruby 核心或标准库功能生成或验证加盐密码,您当然可以。

计算出的带盐的 MD5 密码通常存储在一个平面文件数据库中(例如 /etc/shadow),其中$ 是字段分隔符:

$1$salt$hashed_pw

请注意,前两个字段以明文形式存储,因为当仅显示要验证的密码时,它们需要重建和散列正确的字符串。因此,您需要将盐视为与明文密码分开的变量,尽管盐在散列时与密码包含

如果您的实用程序没有字符限制,生成强盐的一种方法是使用SecureRandom#uuid 生成 UUIDv4 值。例如:

require 'securerandom'

salt = SecureRandom.uuid
#=> "c05280ef-151c-4ebc-83c6-f5f0906f89c2"

然后,您可以根据应用程序的密码实现在 salt + pwpw + salt 上调用您的 MD5 哈希。例如:

require 'digest/md5'

MD5_STR_FMT = '$1$%s$%s'.freeze

salt = 'c05280ef-151c-4ebc-83c6-f5f0906f89c2'
pw   = 'plaintext password gathered securely'

pw_digest = Digest::MD5.new << salt + pw
pw_entry  = MD5_STR_FMT % [salt, pw_digest]
#=> "$1$c05280ef-151c-4ebc-83c6-f5f0906f89c2$87dcc23c0008e45526e474d0364e4aa5"

然后您将 pw_entry 存储在密码数据库文件中,然后在身份验证期间重新计算哈希时解析出盐以添加到提供的密码中。例如:

require 'digest/md5'

# this is how we'll validate a password from user
# input against an entry from the password database
def valid_pw? pw, salt, hashed_pw
  pw_digest = Digest::MD5.new << salt + pw
  pw_digest.to_s.eql? hashed_pw.to_s
end

# extract salt and password from a database entry
def parse_pw_entry str
  str.split(?$).slice -2, 2
end

# get this from your password database in whatever
# way you like
pw_entry = '$1$c05280ef-151c-4ebc-83c6-f5f0906f89c2$87dcc23c0008e45526e474d0364e4aa5'

# for demonstration purposes only; gather password
# securely from user, then perform your validation
['foo', 'plaintext password gathered securely'].map do |pw|
  valid_pw? pw, *parse_pw_entry(pw_entry)
end
#=> [false, true]

【讨论】:

  • 谢谢。这是非常有用和有用的信息。我的目标是针对用于不同应用程序但恰好使用与 /etc/shadow 中使用的相同 crypt-md5 散列机制的非 /etc/shadow 数据存储区验证密码。
【解决方案2】:

您可以像这样添加compute the digest of multiple chunks

require 'digest/md5'

md5 = Digest::MD5.new
md5 << '$1$'
md5 << plaintext

checksum = md5.to_s

或者通过一个方法调用中的盐和文本的字符串连接:

salt = '$1$'
checksum = Digest::MD5.hexdigest("#{salt}#{plaintext}")

【讨论】:

  • 非常感谢。我试过这个,但它给出的结果与为 /etc/passwd 完成的散列不同。我认为在这种情况下盐不是$1$。但是,我偶然发现了一个解决方案,现在我将其发布为我的答案。
【解决方案3】:

我找到了以下内容,它可以满足我的需求......

https://github.com/mogest/unix-crypt

它是这样工作的:

require 'unix_crypt'
checksum = UnixCrypt::MD5.build(plaintext, salt)

这会生成与 /etc/shadow 中使用的相同的校验和,这就是我想要使用它的目的,

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
  • 2020-12-02
相关资源
最近更新 更多