我们正在尝试实现一个函数P_SHA1意味着PHP。用Python编写的函数模式。但是,遗憾的是,有些东西不能正常工作。以下是JAVA中的实现函数:http://ws.apache.org/wss4j/xref/org/apache/ws/security/conversation/dkalgo/P_SHA1.html
我们的代码:
<?php
$newSeed = $label . $seed; // concat as strings
// $p_sha1
$psha1 = p_hash('sha1', $secret, $newSeed, $length);
$string = arrayToBytes($psha1);
/**
* P_SHA1 crypto alg calculation
*
* @return array of bytes - key
**/
function p_hash($algo, $secret, $seed, $length) {
$bytes = array_fill(0, $length, 0);
$tmp = null;
$A = $seed;
$index = 0;
while (1) {
// hmac sha1: secret + seed
$A = hash_hmac($algo, $secret, $A, true);
// hmac sha1: secret + 1st hash + seed
$output = hash_hmac($algo, $secret, ($A . $seed), true);
foreach (bytesToArray($output) as $c) {
if ($index >= $length) {
return $bytes;
}
$bytes[$index] = $c;
$index++;
}
}
return $bytes;
}
function bytesToArray($bytes) { return unpack('C*', $bytes); }
function arrayToBytes($array) { return call_user_func_array("pack", array_merge(array("C*"), $array)); }
?>
也许有人知道我在哪里可以找到现成的解决方案?或者任何人都可以帮助使脚本正常工作?
答案 0 :(得分:3)
这是基于a reply to "signing SOAP message request via ADFS"中包含的C#方法。我已成功使用它来签署SOAP请求并获得我想要的响应。
function psha1($clientSecret, $serverSecret, $sizeBits = 256)
{
$sizeBytes = $sizeBits / 8;
$hmacKey = $clientSecret;
$hashSize = 160; // HMAC_SHA1 length is always 160
$bufferSize = $hashSize / 8 + strlen($serverSecret);
$i = 0;
$b1 = $serverSecret;
$b2 = "";
$temp = null;
$psha = array();
while ($i < $sizeBytes) {
$b1 = hash_hmac('SHA1', $b1, $hmacKey, true);
$b2 = $b1 . $serverSecret;
$temp = hash_hmac('SHA1', $b2, $hmacKey, true);
for ($j = 0; $j < strlen($temp); $j++) {
if ($i < $sizeBytes) {
$psha[$i] = $temp[$j];
$i++;
} else {
break;
}
}
}
return implode("", $psha);
}
需要注意的一点是,客户端密钥和服务器密钥在传递给此函数之前应该进行base64解码。
答案 1 :(得分:1)
您应该已经提到过,它是“WS-SecureConversation 1.3”的实现,显然它不是SHA1,而是具有协议细节的HMAC-SHA1的变体。
原来是TLS (RFC 2246):
我们在RFC 2246中使用为TLS定义的机制的子集。具体来说,我们使用P_SHA-1函数生成可用于生成安全密钥的字节序列。
您不是第一个要问的人,例如这个问题没有回答RFC 2246 PRF function in PHP
答案 2 :(得分:0)
您是否正在寻找现成的SHA1功能或其他功能?这将为您提供SHA1哈希,如果您在第二个参数中输入true,它将以二进制形式提供给您。否则,它将以十六进制给你
答案 3 :(得分:0)
我尝试总结他人的答案,并给出likeuntomurphy's excellent answer的简化版本。
与Yarik stated一样,P_SHA1
在TLS 1.0 standard中定义为PRF,并被合并到WS-SecureConversation 1.3中。值得注意的是,在最新的HKDF中,大约在2018年,这个奇怪的功能已被称为TLS standard的标准功能所代替。
无论如何,这是P_SHA-1的简化代码:
function p_sha1(string $client_secret, string $server_secret, int $num_bytes): string
{
$key = base64_decode($client_secret);
$data = base64_decode($server_secret);
$buff = $data;
$ret = "";
while (strlen($ret) < $num_bytes) {
$buff = hash_hmac("SHA1", $buff, $key, TRUE);
$ret .= hash_hmac("SHA1", $buff . $data, $key, TRUE);
}
return substr($ret, 0, $num_bytes);
}