简体   繁体   English

如何从LDAP检索salt?

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

The organization that I work for uses PPolicy (an OpenLDAP module) to automatically salt and hash passwords. 我工作的组织使用PPolicy(OpenLDAP模块)来自动加密和散列密码。 Unfortunately, I don't have access to the machine running the OpenLDAP server, so i can't look at the config file. 不幸的是,我无法访问运行OpenLDAP服务器的机器,所以我无法查看配置文件。 From what I've seen though, pretty much everything appears to be setup using the default settings. 从我所看到的,几乎所有东西似乎都使用默认设置进行设置。

I'd like to be able to retrieve the salt for a specific user. 我希望能够为特定用户检索salt。 If I look at the user's attributes, userPassword is the SSHA password. 如果我查看用户的属性,userPassword是SSHA密码。 I don't see anything about a salt for that specific user. 我没有看到任何有关该特定用户的盐的信息。 I ended up looking at the LDAP schema and I see nothing about salts there either. 我最终查看了LDAP模式,我也没有看到任何关于盐的信息。

If you were to guess where the salt were being stored for each user, where would it be? 如果您猜测每个用户存储盐的位置,它会在哪里? I understand this is vague and probably not a lot of information, but I can't find anywhere in the OpenLDAP docs that explain where exactly the unique salts are stored. 我知道这很模糊,可能不是很多信息,但我在OpenLDAP文档中找不到任何地方可以解释存储的唯一盐的确切位置。 Perhaps someone who has configured an OpenLDAP server before would know where the default location is. 也许之前配置过OpenLDAP服务器的人会知道默认位置在哪里。

Thank you. 谢谢。

With SSHA, normally the salt is appended to the SHA1 hash and then the whole thing is Base64 encoded (I've never seen an LDAP that didn't do SSHA this way). 使用SSHA,通常将salt附加到SHA1哈希,然后整个事务是Base64编码(我从未见过没有以这种方式执行SSHA的LDAP)。 You should be able to tell this by looking at the userPassword attribute. 您应该能够通过查看userPassword属性来说明这一点。 If it's 28 character long with a = at the end, it's only the hash. 如果它的长度为28个字符,最后一个=,那么它只是哈希值。

If the Base64 value is 32 character long or greater, it contains both the hash and the salt. 如果Base64值为32个字符或更长,则它包含散列和salt。 Base64 decode the value and strip off the first 20 bytes, this is the SHA1 hash. Base64解码该值并去掉前20个字节,这是SHA1哈希。 The remaining bytes are the salt. 剩下的字节是盐。

Example: 例:

                     Base64 encoded hash with salt
userPassword: {SSHA}MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0

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

Edit: After double checking, it seems that variable length salts are sometimes supported. 编辑:经过双重检查,似乎有时支持可变长度的盐。 Corrected the encoding description to account for this. 更正了编码说明以解决此问题。

The post of Syon did help me a lot, thanks for that! Syon的帖子对我帮助很大,谢谢! I thought a working test would be a nice extra for someone else struggling with this topic ;). 我认为对于那些在这个话题上苦苦挣扎的人来说,工作测试会是一个很好的补充;)。

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);
    }
}

In PHP, this compares a plain text password (usually entered by a user) to a given ssha hash (usually stored in your db): 在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