将Windows CryptoAPI Salt和哈希转换为PHP
我们有一个遗留应用程序,它使用Windows CryptoAPI的CryptoHashData函数创建Salt和哈希。我们获取一个随机字节字符串,应用散列,然后再次使用CryptoHashData将该散列应用于第二个数据字符串。这是代码。对随机密钥进行散列,然后使用秘密数据再次进行散列将Windows CryptoAPI Salt和哈希转换为PHP,php,hash,cryptography,salt,cryptoapi,Php,Hash,Cryptography,Salt,Cryptoapi,我们有一个遗留应用程序,它使用Windows CryptoAPI的CryptoHashData函数创建Salt和哈希。我们获取一个随机字节字符串,应用散列,然后再次使用CryptoHashData将该散列应用于第二个数据字符串。这是代码。对随机密钥进行散列,然后使用秘密数据再次进行散列 BYTE baKeyRandom[10] = {87,253, ...}; pszSecret = 'ABCDEF-G...'; ::CryptCreateHash(hCryptProv, CALG_MD5,
BYTE baKeyRandom[10] = {87,253, ...};
pszSecret = 'ABCDEF-G...';
::CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hSaveHash);
::CryptHashData(hSaveHash, baKeyRandom, (DWORD)sizeof(baKeyRandom), 0);
::CryptHashData(hSaveHash, (LPBYTE)T2CW(pszSecret), (DWORD)_tcslen(pszSecret) * sizeof(WCHAR), 0);
通过使用简单的md5()函数散列随机字节字符串bakeydrandom,我们已经能够在PHP上重新创建第一步。此哈希返回的值与::CryptoHashData上的第一个哈希完全匹配
$random = md5($random);
完全符合
::CryptHashData(hSaveHash, baKeyRandom, (DWORD)sizeof(baKeyRandom), 0);
我们还没有弄清楚CryptoAPI是如何将缓冲区中的第一个哈希值与第二个数据字符串结合起来进行哈希处理的。i、 e.我们如何重新创建项目的第二步
::CryptHashData(hSaveHash, (LPBYTE)T2CW(pszSecret), (DWORD)_tcslen(pszSecret) * sizeof(WCHAR), 0);
我们尝试了以下最明显的方法:
$random = md5($random); followed by any of the below
$key = md5($random.$secret);
$key = md5($secret.$random);
$key = md5($random.md5($secret));
$key = md5(md5($secret).$random);
这些方法都不匹配CryptoHashData(随机)+CryptoHashData(机密)中的值
有人知道CryptoHashData将如何组合缓冲区中的两个值,然后对它们进行散列吗?有没有人在其他可以在PHP中复制的平台上重新创建了这个CryptoAPI哈希+salt方法?是的,我们知道这是不安全的,它不被用于密码或PII。我们希望摆脱这种陈旧且不安全的方法,但我们需要采取这一临时步骤,首先将原始加密转换为PHP,以实现与现有部署系统的互操作性。任何帮助或指导都将不胜感激
以下是基于以下公认答案的最终工作代码
<?php
function main(){
$random = pack('c*', 22,194,253,.......);
$secret = pack('c*', 22,194,253,.......);
$hash = hash_init("md5");
hash_update($hash, $random);
hash_update($hash, $secret);
print(hash_final($hash));
}
main();
?>
您不能在PHP中使用md5()
函数进行哈希的渐进更新哈希算法的链接基于算法的内部状态,而不是输入。当我们使用md5()
方法时,无法传输md5的内部状态,因此无法进行渐进更新
流哈希需要使用hash_init()
、hash_update()
和hash_final()
。以下是一个例子:
<?php
$hash = hash_init("md5");
$data1="ABCD";
hash_update($hash, $data1);
$data2="ABCD";
hash_update($hash, $data2);
print(hash_final($hash));
?>
此代码结果将类似于您的Windows API调用。首先,将帮助您了解CryptHashData的操作方式。另请参见API
$key=md5($random.$secret)代码>这必须是可行的,但是,您必须处理字符串转换。在处理字符串转换之前,您还可以用两个数组来测试它。@kelalaka,谢谢您的回复。我已经阅读了你提到的前一篇文章,正如你所看到的,我已经尝试了这里描述的方法组合。不清楚当第二个散列与包含第一个散列的缓冲区组合时会发生什么。它说它是附加的,但我认为还有更多。我还使用了文档链接中提到的CryptoAPI的CryptoGetHashParam函数,这就是我如何判断第二个哈希的结果与PHP结果不匹配的原因。PHP似乎以与CryptoAPI不同的方式处理salt。除非我对您所说的感到困惑,否则您描述的测试正是我正在做的,并且结果不匹配。请注意,我无法更改Windows端的任何方法,因为尽管我已创建了测试版本,但该代码无法更改。md5 random+md5($random.$secret)与CryptoHashData random+不匹配(CryptoHashData random+secret)数组和秘密值是固定的,因此不同之处在于它们各自的处理方式,这正是我试图弄清楚的。嗨@Kellalaka,我现在已经尝试了一个简单的测试,您使用CryptoGetHashParam在两个阶段中描述和监视哈希结果。CryptoHashData random1的第一个哈希与md5($random1)完全匹配。第二个CryptoHashData random1+random2不匹配$key=md5($random.$secret)的任何组合$密钥=md5($secret.$random)$key=md5($random.md5($secret))$key=md5(md5($secret)。$random);双方对第一个散列使用相同的字节数组,我只是将其复制为第二个散列的输入,以保持其非常简单。Hash 1匹配,Hash 2不匹配。嗨@Afshin,你真棒!这正是我们所需要的。现在,第二个哈希的结果在两个系统上完全匹配。Windows CryptoHashData+CryptoHashData+CryptoHashGetParam现在匹配哈希_更新($hash,$data1)+哈希_更新($hash,data2)+打印(哈希_最终($hash));。谢谢你的圣诞礼物!