![](/img/trans.png)
[英]How can I with Ruby check if SHA1 username, password and verifier/salt is correct?
[英]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.