【问题标题】:Verifying Django Password in Ruby on Rails gives non-matching password在 Ruby on Rails 中验证 Django 密码会给出不匹配的密码
【发布时间】:2013-03-28 17:31:12
【问题描述】:

我正在用 Ruby on Rails 重写一个 Django 应用程序,并希望为用户保留旧密码。

Django 使用 PBKDF2SHA1 作为加密机制。所以我有一个加密密码是这个

pbkdf2_sha256$10000$YsnGfP4rZ1IZ$Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBPUgmunFOW4=

原密码为2bulls

在 Ruby 中,我使用 PBKDF256 gem 和 base64 进行检查。

Base64.encode64 PBKDF256.dk("2bulls", "YsnGfP4rZ1IZ", 10000, 32)

期待

Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBPUgmunFOW4=

但是,我得到了

YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU=

有什么想法吗?

更新

如果对您更有意义,请在 django 源代码中找到代码。

class PBKDF2PasswordHasher(BasePasswordHasher):
    """
    Secure password hashing using the PBKDF2 algorithm (recommended)

    Configured to use PBKDF2 + HMAC + SHA256 with 10000 iterations.
    The result is a 64 byte binary string.  Iterations may be changed
    safely but you must rename the algorithm if you change SHA256.
    """
    algorithm = "pbkdf2_sha256"
    iterations = 10000
    digest = hashlib.sha256

    def encode(self, password, salt, iterations=None):
        assert password
        assert salt and '$' not in salt
        if not iterations:
            iterations = self.iterations
        hash = pbkdf2(password, salt, iterations, digest=self.digest)
        hash = base64.b64encode(hash).decode('ascii').strip()
        return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)

    def verify(self, password, encoded):
        algorithm, iterations, salt, hash = encoded.split('$', 3)
        assert algorithm == self.algorithm
        encoded_2 = self.encode(password, salt, int(iterations))
        return constant_time_compare(encoded, encoded_2)

    def safe_summary(self, encoded):
        algorithm, iterations, salt, hash = encoded.split('$', 3)
        assert algorithm == self.algorithm
        return SortedDict([
            (_('algorithm'), algorithm),
            (_('iterations'), iterations),
            (_('salt'), mask_hash(salt)),
            (_('hash'), mask_hash(hash)),
        ])

结论:

原来只有密码为2bulls的账号才有这个问题。其他账号没问题。当我知道 2bulls 密码不一致的确切原因后,我会在这里发布。

【问题讨论】:

  • 我假设您使用的 salt 来自 Django 安装,并且迭代号也来自那里($10000$ 在第一个密码中?)。长度匹配。有没有可能是 Base64 编码的问题?
  • 是的。第二个论点是盐。第三个参数是迭代次数,最后一个参数是密钥长度。我现在正在研究 django 源代码进行调查。
  • 啊,有趣。我现在看到您从哪里得出所有论点。所以首先它得到一个 sha256 摘要,然后通过 pbkdf2 运行它,然后是 base64 编码。这就是 Ruby gem 正在做的事情吗? (我也会看看。)另外,我们能否验证 Python 的 sha256 哈希在同一字符串上生成与 Ruby 相同的输出?这似乎是一个最小公分母。
  • aaaah,没关系,gem 没有使用 Ruby 的 sha256,它使用的是自己的基于 C 的版本。我已经过头了。

标签: ruby-on-rails ruby django encryption


【解决方案1】:

如果您使用以下脚本对密码 2bulls 进行哈希处理(与 Django 用于哈希密码的逻辑相同),这就是您得到的(在 Django 的 shell 上运行):

>>> import base64, hashlib
>>> hash = pbkdf2("2bulls","YsnGfP4rZ1IZ", 10000, 32, hashlib.sha256)
>>> hash.encode('base64').strip()
'YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU='

注意我使用的参数与您在 Ruby 中使用的参数相同:

password = "2bulls"
salt = "YsnGfP4rZ1IZ"
iterations = 10000
dklen = 32
digest = hashlib.sha256

您确定您的预期哈希值对应于密码2bulls 吗?

【讨论】:

    【解决方案2】:

    我刚刚为此发布了一个 gem。我也得到与@Daniel Aronne 相同的结果:

    require 'pbkdf2_password_hasher'
    
    puts Pbkdf2PasswordHasher::hash_password('2bulls','YsnGfP4rZ1IZ',10000,32)
    #=> "YEfK6oUGFHdaKZMDXC0Dz8TpwsJlKfqC5vjCxjo+ldU="
    

    【讨论】:

      猜你喜欢
      • 2011-07-04
      • 2018-10-24
      • 2019-02-08
      • 2017-10-03
      • 2014-10-18
      • 1970-01-01
      • 2013-01-10
      • 2013-01-04
      • 1970-01-01
      相关资源
      最近更新 更多