繁体   English   中英

如何从LDAP检索salt?

[英]How can I retrieve a salt from LDAP?

我工作的组织使用PPolicy(OpenLDAP模块)来自动加密和散列密码。 不幸的是,我无法访问运行OpenLDAP服务器的机器,所以我无法查看配置文件。 从我所看到的,几乎所有东西似乎都使用默认设置进行设置。

我希望能够为特定用户检索salt。 如果我查看用户的属性,userPassword是SSHA密码。 我没有看到任何有关该特定用户的盐的信息。 我最终查看了LDAP模式,我也没有看到任何关于盐的信息。

如果您猜测每个用户存储盐的位置,它会在哪里? 我知道这很模糊,可能不是很多信息,但我在OpenLDAP文档中找不到任何地方可以解释存储的唯一盐的确切位置。 也许之前配置过OpenLDAP服务器的人会知道默认位置在哪里。

谢谢。

使用SSHA,通常将salt附加到SHA1哈希,然后整个事务是Base64编码(我从未见过没有以这种方式执行SSHA的LDAP)。 您应该能够通过查看userPassword属性来说明这一点。 如果它的长度为28个字符,最后一个=,那么它只是哈希值。

如果Base64值为32个字符或更长,则它包含散列和salt。 Base64解码该值并去掉前20个字节,这是SHA1哈希。 剩下的字节是盐。

例:

                     Base64 encoded hash with salt
userPassword: {SSHA}MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0

Base64 decoded value
     SHA1 Hash      Salt
--------------------++++
123456789012345678901234

编辑:经过双重检查,似乎有时支持可变长度的盐。 更正了编码说明以解决此问题。

Syon的帖子对我帮助很大,谢谢! 我认为对于那些在这个话题上苦苦挣扎的人来说,工作测试会是一个很好的补充;)。

public class SshaPasswordVerifyTest {
    private final static int SIZE_SHA1_HASH = 20;

    @Test
    public void itShouldVerifyPassword() throws Exception{
        String password = "YouNeverGuess!";
        String encodedPasswordWithSSHA = "{SSHA}M6HeeJAbwUCzuLwXbq00Fc3n3XcxFI8KjQkqeg==";
        Assert.assertEquals(encodedPasswordWithSSHA, getSshaDigestFor(password, getSalt(encodedPasswordWithSSHA)));
    }

    // The salt is the remaining part after the SHA1_hash
    private byte[] getSalt(String encodedPasswordWithSSHA){
        byte[] data = Base64.getMimeDecoder().decode(encodedPasswordWithSSHA.substring(6));
        return Arrays.copyOfRange(data, SIZE_SHA1_HASH, data.length);
    }

    private String getSshaDigestFor(String password, byte[] salt) throws Exception{
        // create a SHA1 digest of the password + salt
        MessageDigest crypt = MessageDigest.getInstance("SHA-1");
        crypt.reset();
        crypt.update(password.getBytes(Charset.forName("UTF-8")));
        crypt.update(salt);
        byte[] hash = crypt.digest();

        // concatenate the hash with the salt
        byte[] hashPlusSalt = new byte[hash.length + salt.length];
        System.arraycopy(hash, 0, hashPlusSalt, 0, hash.length);
        System.arraycopy(salt, 0, hashPlusSalt, hash.length, salt.length);

        // prepend the SSHA tag + base64 encode the result
        return "{SSHA}" + Base64.getEncoder().encodeToString(hashPlusSalt);
    }
}

在PHP中,这会将纯文本密码(通常由用户输入)与给定的ssha散列(通常存储在数据库中)进行比较:

private function checkSshaPassword($encrypted_password, $password)
{
    //  get hash and salt from encrypted_password
    $base_64_hash_with_salt = substr($encrypted_password, 6);
    $hash_with_salt = base64_decode($base_64_hash_with_salt);
    $hash = substr($hash_with_salt, 0, 20);
    $salt = substr($hash_with_salt, 20);

    //  hash given password
    $hash_given = sha1($password . $salt, true);

    return ($hash == $hash_given);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM