在C#中可靠地再现在PHP中实现的传统密码散列方法
我们正在将一个在Linux上运行的PHP应用程序迁移到我们新的单点登录(SSO)基础设施,该基础设施在C#中实现,并在Windows上运行 作为迁移过程的一部分,我们需要我们的C#SSO基础设施能够以与PHP应用程序完全相同的方式散列密码 虽然PHP应用程序使用了一种相当合理的密码哈希算法,但除了密码和salt之外,不幸的是,被哈希的字符串还包含salt值的余弦(解释为整数)。。。一个相当不寻常的决定,说得中庸一点 不出所料,在PHP和C#中计算一个大整数的余弦会得到稍微不同的结果。这意味着我们可能无法在新的SSO基础架构中可靠地重新实现遗留密码哈希算法 我们考虑的一个解决方案是在AWS Lambda中运行PHP密码哈希函数,并从我们的SSO基础结构中查询该Lambda 你能想到其他的选择吗?PHP将是glibc的在C#中可靠地再现在PHP中实现的传统密码散列方法,c#,php,hash,passwords,C#,Php,Hash,Passwords,我们正在将一个在Linux上运行的PHP应用程序迁移到我们新的单点登录(SSO)基础设施,该基础设施在C#中实现,并在Windows上运行 作为迁移过程的一部分,我们需要我们的C#SSO基础设施能够以与PHP应用程序完全相同的方式散列密码 虽然PHP应用程序使用了一种相当合理的密码哈希算法,但除了密码和salt之外,不幸的是,被哈希的字符串还包含salt值的余弦(解释为整数)。。。一个相当不寻常的决定,说得中庸一点 不出所料,在PHP和C#中计算一个大整数的余弦会得到稍微不同的结果。这意味着我们
math.h
的cos
实现。您可以看看该实现并在应用程序中重新创建它吗?这可能会令人毛骨悚然,因为glibc的数学知识相当复杂。如果在应用程序中使用glibc作为依赖项是可以接受的,那么您可以尝试这种方法吗?不管怎样,这就是我要开始的地方
另一个让我担心的问题是,您实际上也在处理一些PHP的奇数浮点处理,因此并非算法的所有“字符”都来自所涉及的trig函数。在您编写的另一个问题中 用Visual Studio 2017编译的简单C程序中的C的
cos(double)
函数
c = -0.57977754519881342
虽然您没有直截了当地说出来,但这似乎就是您要寻找的结果(它肯定与Math.Cos
的结果不同,不确定它是否与PHP按位相同)
因此,使用VS2017编译一个DLL,并p/调用它。或者在C运行时库DLL中P/invokecos()
,它肯定会导出所有这些#include
函数
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
据推测,盐与每个密码一起存储。您可以使用PHP代码计算余弦,并将其与密码一起存储。然后,我还会添加一个密码版本号,并将所有旧密码默认为版本1。然后,在您的C#代码中,对于任何新密码,您实现了一个新的哈希算法,并将这些密码哈希存储为密码版本2。对于任何版本1密码,要进行身份验证,您不必计算余弦,只需使用与密码哈希和salt一起存储的余弦即可。
那个PHP代码的程序员可能想做一个聪明的pepper版本。通过存储余弦或胡椒粉以及盐和密码散列,基本上将胡椒粉更改为salt2。因此,另一种无版本的方法是在C#哈希代码中使用两种盐。对于新密码,您可以将第二个salt留空或以其他方式分配。对于旧密码,它应该是余弦,但它已经计算出来了。嗨,本,这正是我最终实现的解决方案。我创建了一个很小的DLL,它只是包装了use
cos()
,但我还没有想到要使用msvcr120.DLL
!P/从C运行时调用cos()
,效果非常好。太棒了,谢谢你的建议!有一个微妙之处:如果C#project P/Invokingmsvcr120.dll
是为“任何CPU”平台构建的,那么就使用x86版本的msvcr120.dll
而不是x64版本,从而导致不精确的cos()
版本。…@franceçoisbaune:我认为如果您构建自己的dll并指定使用SSE2进行浮点运算,你在x86上应该还好吧?您也可以尝试更新版本的C运行时(它们不再保存在System32中,因此除了p/invoke之外,C#app可能需要一些清单更改),不幸的是,我找不到一种方法来指示VC++使用自己的基于SSE[2]的cos()实现,而不是32位模式下的x87指令。我还尝试了VC++2017的标准库(api-ms-win-crt-math-l1-1-0.dll
),但它给出了同样不准确的结果……最终我将这个答案移到了这里!(来自)。。。一年多过去了,我让你们大家都想知道为什么现在。