是否可以将 Linux salted sha512 密码哈希转换为 LDAP 格式?

是否可以将 Linux salted sha512 密码哈希转换为 LDAP 格式?

我们有一个 LDAP 服务器,用于存储密码和其他用户数据。
不过,该服务器不用于客户端计算机的身份验证,而仅用于客户端应用程序的身份验证。
因此,用户可以在客户端本地更改密码。
只要我们使用 crypt,我就可以将 Linux 哈希存储为 {CRYPT}$hash 存储在 LDAP 中,这样就可以正常工作。
现在,密码存储为加盐的 sha512 哈希
,/etc/shadow 中的密码格式如下:

printf( "$6$%s$%s", $salt, $hash )  

$salt 似乎只是一个 ASCII 字符串,
我认为 $hash 来自 $plainPW 和 $salt 连接的 sha512 摘要的 Base64 编码结果,但我不确定。

相反,LDAP 存储密码哈希值,如下所示:

printf( "{SSHA512}%s", $_96byteString )  

其中$_96byteString是$saltedPWhash和$salt的512位串联的base64编码结果

我尝试对 $hash 进行 base64_decode,附加 $salt,对结果进行 base64_encode,并将其存储为上述 LDAP 格式的 $_96byteString。
唉,LDAP 无法对此进行身份验证,简单的 ldapbind 就失败了。

有谁知道如何转换 linux sha512 哈希值以便 LDAP 服务器接受它为有效?

我发现 linux crypt 使用与标准 mime 不同的 base64 编码。
标准使用 [A-Za-z0-9+/],而 crypt 使用 [./0-9A-Za-z]。
所以我尝试用 tr 进行转换,但结果仍然失败:-(

答案1

我认为这是不可行的。

正如 @Eir Nym 所说,在不知道密码的情况下,您显然无法将密码的 MD5 哈希值转换为 SHA-256 哈希值。

然而你会思考您可以将 SHA-256 哈希值(根据 crypt(3))转换为 SHA-256 哈希值(根据 OpenLDAP):当然,这只是以一种格式识别盐和哈希值并重新排序的问题将它们转换成对方期望的格式。不?什么,不是吗?!

在 OpenLDAP 中,属性的格式userPassword虽然没有完全记录,但相对简单:它是密码的固定长度散列,后跟盐(参见 contrib/slapd-modules/passwd/sha2例如OpenLDAP 来源)。这在注释中也很明显,例如这篇 OpenLDAP FAQ-o-matic 文章它展示了如何{SSHA}从密码+盐生成哈希。

然而,对于使用 crypt(3) 的系统,您将看到以下形式的“密码哈希”

$id$salt$hash

其中$5$表示 SHA-256,$6$表示 SHA-512,依此类推。其中的元素 hash是密钥、盐和(在某些变体中)加密轮数的某些函数的 Base64 编码形式,但实际函数......没有记录。

  • 关于地穴的维基百科页面(3) 提到“随着时间的推移,已经引入了各种算法。”
  • 它指向“密码哈希竞赛” 规范(PHC),它缩小了“哈希”字符串的总体格式,但没有您希望的那么多。它甚至没有最终确定该字符串使用的 Base64 变体(看起来确实如此,但承认字符[.-]可以出现在 Base64 字符串中,而无需说明它们是什么)。
  • 密码库 承认存在一些混乱(“以上所有内容都是基于对现有哈希值和操作系统实现的检查的猜测”)并推荐 PHC 格式。
  • Alinuxquestions.org 问题 表明相关的base64编码比较特殊。

所以我们可以看看glibc 源代码 对于地穴。在那里,我们发现(在crypt_util.c)base64 字母表确实很奇怪,使用的"./0-9A-Za-b"是而不是更常见的(并且是 PHC 指定的)"A-Za-z0-9+/"(最后两个字符偶尔有变体)。没有帮助,但如果这是唯一的区别,我们可以应对。

然而,sha256-crypt.c该库中的函数(例如)采用密钥和盐,并用它们做了一些非常奇怪和冗长的事情来产生值hash。我不想冒险对它所做的事情是否明智发表意见,但这肯定不是直截了当的。

这意味着,尽管 crypt(3)$5$和 OpenLDAP 'SHA-256' 哈希值表面上使用相同的加密原语,但它们实际上以完全不同的方式使用它,它们相当于不同的哈希函数因此,与顶部的点一样,在不知道密码的情况下,您无法将其中一个转换为另一个。对于$6$/SHA-512 密码也可以得出类似的结论。

这很烦人。


附注:碰巧,可以$1$在 crypt(3) 格式和 OpenLDAP 之间转换 /SMD5 '哈希值':

$1$salt$hash

对应于

'{SMD5}' + hash + salt

其中+是简单的字符串连接。但我们可能不应该再使用 MD5 哈希值,所以这没有多大帮助。

另请注意,您可以将 crypt(3) 哈希值不变地移植到 OpenLDAP,使用

{CRYPT}$1$salt$hash

如果你的 libc 兼容(如果 OpenLDAP 在 Linux 上运行,则通常会如此),但 OpenLDAP 不会以这种方式生成新密码,因此这是一条单行道。

答案2

简而言之,答案是否定的,如果您不知道原始密码并且不使用暴力或任何其他攻击,则无法直接将一个密码哈希重新编码为另一个密码哈希。但是您可以构建透明层,如果密码正确,则转换哈希值。

这个问题已经被问过很多次了,比如这里

在我的软件中我使用密码库库可以在没有我的拦截的情况下执行此操作。

答案3

您可以简单地使用前缀{CRYPT}添加任何密码哈希/etc/shadow用户密码value 提供了保存本地帐户数据的系统和 LDAP 服务器上的 crypt(3) 函数,两者都实现相同的哈希方案。检查不同系统的 crypt(3) 手册页。

当设置密码时,您还可以让 OpenLDAP 的 slapd 生成具有特定哈希模式和盐格式的 crypt(3) 哈希值LDAP密码修改扩展操作(也可以看看slapd.conf):

password-hash {CRYPT}
password-crypt-salt-format "$6$rounds=20000$%.16s"

实际上,上面的示例比 {SSHA512} 更好,因为使用了 20000 次哈希轮次,而不是仅一次,这增加了进行暴力攻击所需的工作量。

相关内容