【问题标题】:Reliably reproduce in C# a legacy password hashing method implemented in PHP在 C# 中可靠地重现在 PHP 中实现的旧密码散列方法
【发布时间】:2017-12-15 06:34:58
【问题描述】:

我们正在将一个在 Linux 上运行的 PHP 应用程序迁移到我们用 C# 实现并在 Windows 上运行的新单点登录 (SSO) 基础架构。

作为迁移过程的一部分,我们需要 C# SSO 基础架构能够以与 PHP 应用程序完全相同的方式对密码进行哈希处理。

虽然 PHP 应用程序使用了一种相当合理的密码散列算法,但除了密码和盐之外,不幸的是,被散列的字符串还包含盐值的余弦值(解释为整数)。 .. 一个相当不寻常的决定,把它放在中间。

不出所料,在 PHP 和 C# 中计算大整数的余弦会导致结果略有不同。这意味着我们可能无法在新的 SSO 基础架构中可靠地重新实现旧密码哈希算法。

我们想到的一个解决方案是在 AWS Lambda 中运行 PHP 密码哈希函数,并从我们的 SSO 基础设施中查询该 Lambda。

你能想到其他选择吗?

【问题讨论】:

    标签: c# php hash passwords


    【解决方案1】:

    在你的另一个问题中你写了这个

    使用 Visual Studio 2017 编译的简单 C 程序中的 C 的 cos(double) 函数给出了

    c = -0.57977754519881342
    

    虽然你没有直接说出来,但这似乎是你正在寻找的结果(它肯定与Math.Cos 的结果不同,不确定它是否与 PHP 按位相同)。

    所以用 VS2017 编译一个 DLL 并 P/invoke 它。或者在 C 运行时库 DLL 中 P/invoke cos(),它肯定会导出所有这些 #include <math.h> 函数。

    c:\Windows\System32>dumpbin /exports msvcr120.dll | find "cos"
           1442  5A1 00081C44 acos
           1443  5A2 00081F2C acosf
           1444  5A3 000821B8 acosh
           1445  5A4 0008227C acoshf
           1446  5A5 0008233C acoshl
           1472  5BF 00083ED4 cacos
           1473  5C0 00084208 cacosf
           1474  5C1 000844BC cacosh
           1475  5C2 00084824 cacoshf
           1476  5C3 00084AF4 cacoshl
           1477  5C4 00084E5C cacosl
           1497  5D8 00086CF4 ccos
           1498  5D9 00086D70 ccosf
           1499  5DA 00086EAC ccosh
           1500  5DB 0008714C ccoshf
           1501  5DC 000873AC ccoshl
           1502  5DD 0008756C ccosl
           1526  5F5 00088640 cos
           1527  5F6 00088BA0 cosf
           1528  5F7 000890A0 cosh
           1529  5F8 00089574 coshf
    
    c:\Windows\System32>dumpbin /exports msvcrt.dll | find "cos"
           1046  415 000372D0 acos
           1047  416 00019BE0 acosf
           1069  42C 000118F0 cos
           1070  42D 00015480 cosf
           1071  42E 000868F0 cosh
           1072  42F 0001ABC0 coshf
    

    【讨论】:

    • 嗨 Ben,这正是我最终实施的解决方案。我创建了一个很小的 ​​DLL,只是包装使用 cos(),虽然没有使用 msvcr120.dll
    • P/Invoking cos() 从 C 运行时工作就像一个魅力。太棒了,谢谢你的建议!
    • 有一个微妙之处:如果 C# 项目 P/Invoking msvcr120.dll 是为“Any CPU”平台构建的,那么使用 x86 版本的 msvcr120.dll 而不是 x64 版本,导致cos() 的不精确版本...
    • @FrançoisBeaune:我认为如果您构建自己的 DLL 并指定使用 SSE2 进行浮点运算,您应该可以在 x86 上使用吗?您也可以尝试更新版本的 C 运行时(它们不再保留在 System32 中,因此除了 p/invoke 之外,C# 应用程序可能需要一些清单更改)
    • 不幸的是,我找不到一种方法来指示 VC++ 使用其自己的基于 SSE[2] 的 cos() 实现,而不是 32 位模式下的 x87 指令。我还尝试了 VC++ 2017 的标准库 (api-ms-win-crt-math-l1-1-0.dll),但它给出了同样不准确的结果......
    【解决方案2】:

    PHP 将是来自 glibc 的 math.hcos 实现 calling。您可以查看该实现并在您的应用程序中重新创建它吗?由于 glibc 的数学内容非常复杂,因此这可能会变得很棘手。如果在您的应用程序中将 glibc 作为依赖项是可以接受的,您可以尝试这种方法吗?无论如何,这就是我要开始的地方。

    我担心的另一个问题是,您实际上也在处理 PHP 的一些奇怪的浮点处理,因此并非算法的所有“字符”都来自所涉及的三角函数。

    【讨论】:

      【解决方案3】:

      大概,盐与每个密码一起存储。您可以使用 PHP 代码计算余弦,并将其与密码一起存储。然后,我还将添加一个密码版本号,并将所有旧密码默认为版本 1。然后,在您的 C# 代码中,对于任何新密码,您实现一个新的哈希算法,并将这些密码哈希存储为密码版本 2。任何版本 1 的密码,要进行身份验证,您不必计算余弦,您只需使用与密码哈希和盐一起存储的那个。

      那个 PHP 代码的程序员可能想要做一个聪明的辣椒版本。通过将该余弦或胡椒与盐和密码哈希一起存储,您基本上可以将该胡椒更改为 salt2。因此,另一种无版本的方法是在 C# 哈希代码中使用两种盐。对于新密码,您可以将第二个盐留空或以其他方式分配。对于旧密码,它会是那个余弦,但它已经计算过了。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多