在Java / Scala中重现CouchDB 1.2.0密码哈希函数

时间:2013-01-04 10:05:20

标签: java scala erlang couchdb

我有一个简单的设置,其中一个app服务器支持CouchDB,我在其中使用CouchDB的内置用户身份验证给应用服务器的用户。应用服务器可以访问_users数据库并检索用户的文档。

我正在尝试复制密码哈希函数,以便我可以在应用服务器中验证用户的密码,而无需对CouchDB进行身份验证。

CouchDB安全规范声明:

  

“password_sha”属性是在字符串上计算的SHA-1哈希的十六进制表示形式,该字符串与用盐连接的用户密码(理想情况下是随机字符串)相匹配。 salt属性是用于生成用户密码哈希的salt的十六进制表示。

     

从CouchDB 1.2.0开始,当用户文档中存在密码字段时,会自动创建password_sha和salt字段。写入用户文档时,CouchDB会检查密码字段是否存在,如果存在,它将生成一个salt,哈希密码字段的值并散列密码哈希和salt的串联。然后它将生成的密码写入password_sha字段,盐写入salt字段。密码`字段已删除。

相关源代码:

% Lines 72-74 of couch_httpd_auth.erl

UserSalt = couch_util:get_value(<<"salt">>, UserProps, <<>>),
PasswordHash = hash_password(?l2b(Pass), UserSalt),
ExpectedHash = couch_util:get_value(<<"password_sha">>, UserProps, nil),

% Lines 237-238 of couch_httpd_auth.erl

hash_password(Password, Salt) ->
    ?l2b(couch_util:to_hex(crypto:sha(<<Password/binary, Salt/binary>>))).

这是我尝试使用密码为“password”的测试用户复制它:

import java.security.MessageDigest
import org.apache.commons.codec.binary.Hex
import org.specs2.mutable.Specification

class PasswordSpec extends Specification {

    "Password" should {
        "match" in {

            val password = "password"

            val hexEncodedPasswordHash = "0fed560a9928b50761ebec5aa97c815999e6def0"
            val hexEncodedSalt = "2ba345d5f2880fae25de9ec7a78d38ae"

            val charset = "UTF-8"
            val codec = new Hex(charset)

            val md = MessageDigest.getInstance("SHA-1")
            md.reset()
            md.update(password.getBytes(charset))
            md.update(codec.decode(hexEncodedSalt.getBytes(charset)))
            val hashBytes = md.digest()
            val hexEncodedHash = new String(codec.encode(hashBytes), charset)

            hexEncodedHash mustEqual(hexEncodedPasswordHash)

        }
    }
}

这个测试失败了,我已经没想到为什么了。

1 个答案:

答案 0 :(得分:0)

我明白了。在与密码字节连接之前,不需要从十六进制解码salt字节。