簡體   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