解码 CS:GO 与 PHP 匹配的共享代码
Decode a CS:GO match sharing code with PHP
我正在尝试构建一个解码 CS:GO 匹配共享代码的函数。我已经看过足够多的示例,但所有内容都在 JS 或 C# 中,但在 PHP.
中什么都没有
我以akiver demo manager为例,并试图在PHP中复制它。我有点盲目,因为我不知道某些点的输出是什么,所以我只能希望结果是我所期望的。我认为我走在正确的道路上,当字节必须 created/interpeted/converted 达到期望的结果时就会出现问题。
应解码的代码如下:'CSGO-oPRbA-uTQuR-UFkiC-hYWMB-syBcO'
($getNextGame
变量)
结果应该是3418217537907720662
到目前为止我的代码:
/**
* @param $getNextGame
* @return array
*/
public function decodeDemoCode(string $getNextGame): array
{
$shareCodePattern = "/CSGO(-?[\w]{5}){5}$/";
if (preg_match($shareCodePattern, $getNextGame) === 1) {
$result = [];
$bigNumber = 0;
$matchIdBytes = $outcomeIdBytes = $tvPortIdBytes = [];
$dictionary = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789";
$dictionaryLength = strlen($dictionary);
$changedNextGame = str_replace(array("CSGO", "-"), "", $getNextGame);
$chars = array_reverse(str_split($changedNextGame));
foreach ($chars as $char) {
$bigNumber = ($bigNumber * $dictionaryLength) + strpos($dictionary, $char);
}
}
}
这让我想起了类似的事情:
1.86423701402E+43 (double)
那么我有以下内容:
$packed = unpack("C*", $bigNumber);
$reversedPacked = array_reverse($packed);
这带来了以下结果:
array(17 items)
0 => 51 (integer)
1 => 52 (integer)
2 => 43 (integer)
3 => 69 (integer)
4 => 50 (integer)
5 => 48 (integer)
6 => 52 (integer)
7 => 49 (integer)
8 => 48 (integer)
9 => 55 (integer)
10 => 51 (integer)
11 => 50 (integer)
12 => 52 (integer)
13 => 54 (integer)
14 => 56 (integer)
15 => 46 (integer)
16 => 49 (integer)
现在我真的不确定该怎么做,因为我不完全理解 C#,而且我以前从未使用过 PHP 中的字节。
通常 return 类型应该是一个数组,看起来像这样:
$result = [
matchId => 3418217537907720662,
reservationId => 3418217537907720662,
tvPort => 55788
];
提前致谢。非常感谢任何帮助
我创建了一个 PHP class 这使得这成为可能:
您必须解决的第一个问题是 returned double 值。 PHP 对于大整数有限制。更多信息请参见 What is the maximum value for an integer in PHP.
由于此限制,您正在失去精度,从而导致结果不准确。为了解决这个问题,您将不得不使用这些库之一 GMB, BC Math。这些库所做的是将结果作为 string 返回给你,它解决了你得到的双精度值。
因此您的代码必须如下所示:
foreach ($chars as $char) {
$bigNumber = gmp_add(
gmp_mul($bigNumber,$dictionaryLength),
strpos($dictionary,$char)
);
}
json_encode($bigNumber);
$result = json_decode($bigNumber, true, 512, JSON_BIGINT_AS_STRING);
这会给你以下"18642370140230194654275126136176397505221000"
您实际上不需要 PHP pack and unpack 函数,因为没有它们也可以生成结果。下一步是将您的数字转换为十六进制。您可以通过以下方式做到这一点:
$toHex = gmp_strval(gmp_init($number, 10), 16);
同样,您需要使用 gmp 库才能获得所需的值。您要做的是确保结果是一个字符串,然后将数字的基数从 10 转换为 16,这相当于十六进制。结果如下:
"d6010080bdf26f2fbf0100007cf76f2f5188"
下一步是将十六进制值转换为字节整数数组。它看起来像这样:
$bytes = [];
$byteArray= str_split($toHex, 2);
foreach ($byteArray as $byte) {
$bytes[] = (int)base_convert($byte, 16, 10);
}
你在这里所做的是将数组拆分为每两个字符。 $byteArray
变量看起来像这样(在进入 foreach 循环之前)
array(18 items)
0 => 'd6' (2 chars) 1 => '01' (2 chars) 2 => '00' (2 chars) 3 => '80' (2 chars)
4 => 'bd' (2 chars) 5 => 'f2' (2 chars) 6 => '6f' (2 chars) 7 => '2f' (2 chars)
8 => 'bf' (2 chars) 9 => '01' (2 chars) 10 => '00' (2 chars) 11 => '00' (2 chars)
12 => '7c' (2 chars) 13 => 'f7' (2 chars) 14 => '6f' (2 chars) 15 => '2f' (2 chars)
16 => '51' (2 chars) 17 => '88' (2 chars)
现在您必须将每个条目转换为整数。由于结果不再那么大,您可以使用 base_convert 函数更改值的基础。基数是 16(十六进制),您必须将其改回 10。foreach 循环后的结果 $bytes
如下所示:
array(18 items)
0 => 214 (integer) 1 => 1 (integer) 2 => 0 (integer) 3 => 128 (integer)
4 => 189 (integer) 5 => 242 (integer) 6 => 111 (integer) 7 => 47 (integer)
8 => 191 (integer) 9 => 1 (integer) 10 => 0 (integer) 11 => 0 (integer)
12 => 124 (integer) 13 => 247 (integer) 14 => 111 (integer) 15 => 47 (integer)
16 => 81 (integer) 17 => 136 (integer)
现在您必须定义哪些字节负责每个结果。
$matchIdBytes = array_reverse(array_slice($bytes, 0, 8));
$reservationIdBytes = array_reverse(array_slice($bytes, 8, 8));
$portBytes = array_reverse(array_slice($bytes, 16, 2));
- 对于匹配 ID,您必须获取前 8 个条目并反转数组
- 对于预订 ID,您必须从第 8 个条目开始获取接下来的 8 个条目并反转数组
- 对于端口,您必须获取最后 2 个条目并反转数组
现在您必须 return 值
return [
'matchId' => $this->getResultFromBytes($matchIdBytes),
'reservationId' => $this->getResultFromBytes($reservationIdBytes),
'tvPort' => $this->getResultFromBytes($portBytes)
];
getResultFromBytes()
函数:
**
* @param array $bytes
* @return string
*/
public function getResultFromBytes(array $bytes): string
{
$chars = array_map("chr", $bytes);
$bin = implode($chars);
$hex = bin2hex($bin);
return gmp_strval($this->gmp_hexDec($hex));
}
/**
* @param $n
* @return string
*/
public function gmp_hexDec($n): string
{
$gmp = gmp_init(0);
$multi = gmp_init(1);
for ($i=strlen($n)-1;$i>=0;$i--,$multi=gmp_mul($multi, 16)) {
$gmp = gmp_add($gmp, gmp_mul($multi, hexdec($n[$i])));
}
return $gmp;
}
此致
我正在尝试构建一个解码 CS:GO 匹配共享代码的函数。我已经看过足够多的示例,但所有内容都在 JS 或 C# 中,但在 PHP.
中什么都没有我以akiver demo manager为例,并试图在PHP中复制它。我有点盲目,因为我不知道某些点的输出是什么,所以我只能希望结果是我所期望的。我认为我走在正确的道路上,当字节必须 created/interpeted/converted 达到期望的结果时就会出现问题。
应解码的代码如下:'CSGO-oPRbA-uTQuR-UFkiC-hYWMB-syBcO'
($getNextGame
变量)
结果应该是3418217537907720662
到目前为止我的代码:
/**
* @param $getNextGame
* @return array
*/
public function decodeDemoCode(string $getNextGame): array
{
$shareCodePattern = "/CSGO(-?[\w]{5}){5}$/";
if (preg_match($shareCodePattern, $getNextGame) === 1) {
$result = [];
$bigNumber = 0;
$matchIdBytes = $outcomeIdBytes = $tvPortIdBytes = [];
$dictionary = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789";
$dictionaryLength = strlen($dictionary);
$changedNextGame = str_replace(array("CSGO", "-"), "", $getNextGame);
$chars = array_reverse(str_split($changedNextGame));
foreach ($chars as $char) {
$bigNumber = ($bigNumber * $dictionaryLength) + strpos($dictionary, $char);
}
}
}
这让我想起了类似的事情:
1.86423701402E+43 (double)
那么我有以下内容:
$packed = unpack("C*", $bigNumber);
$reversedPacked = array_reverse($packed);
这带来了以下结果:
array(17 items)
0 => 51 (integer)
1 => 52 (integer)
2 => 43 (integer)
3 => 69 (integer)
4 => 50 (integer)
5 => 48 (integer)
6 => 52 (integer)
7 => 49 (integer)
8 => 48 (integer)
9 => 55 (integer)
10 => 51 (integer)
11 => 50 (integer)
12 => 52 (integer)
13 => 54 (integer)
14 => 56 (integer)
15 => 46 (integer)
16 => 49 (integer)
现在我真的不确定该怎么做,因为我不完全理解 C#,而且我以前从未使用过 PHP 中的字节。
通常 return 类型应该是一个数组,看起来像这样:
$result = [
matchId => 3418217537907720662,
reservationId => 3418217537907720662,
tvPort => 55788
];
提前致谢。非常感谢任何帮助
我创建了一个 PHP class 这使得这成为可能:
您必须解决的第一个问题是 returned double 值。 PHP 对于大整数有限制。更多信息请参见 What is the maximum value for an integer in PHP.
由于此限制,您正在失去精度,从而导致结果不准确。为了解决这个问题,您将不得不使用这些库之一 GMB, BC Math。这些库所做的是将结果作为 string 返回给你,它解决了你得到的双精度值。
因此您的代码必须如下所示:
foreach ($chars as $char) {
$bigNumber = gmp_add(
gmp_mul($bigNumber,$dictionaryLength),
strpos($dictionary,$char)
);
}
json_encode($bigNumber);
$result = json_decode($bigNumber, true, 512, JSON_BIGINT_AS_STRING);
这会给你以下"18642370140230194654275126136176397505221000"
您实际上不需要 PHP pack and unpack 函数,因为没有它们也可以生成结果。下一步是将您的数字转换为十六进制。您可以通过以下方式做到这一点:
$toHex = gmp_strval(gmp_init($number, 10), 16);
同样,您需要使用 gmp 库才能获得所需的值。您要做的是确保结果是一个字符串,然后将数字的基数从 10 转换为 16,这相当于十六进制。结果如下:
"d6010080bdf26f2fbf0100007cf76f2f5188"
下一步是将十六进制值转换为字节整数数组。它看起来像这样:
$bytes = [];
$byteArray= str_split($toHex, 2);
foreach ($byteArray as $byte) {
$bytes[] = (int)base_convert($byte, 16, 10);
}
你在这里所做的是将数组拆分为每两个字符。 $byteArray
变量看起来像这样(在进入 foreach 循环之前)
array(18 items)
0 => 'd6' (2 chars) 1 => '01' (2 chars) 2 => '00' (2 chars) 3 => '80' (2 chars)
4 => 'bd' (2 chars) 5 => 'f2' (2 chars) 6 => '6f' (2 chars) 7 => '2f' (2 chars)
8 => 'bf' (2 chars) 9 => '01' (2 chars) 10 => '00' (2 chars) 11 => '00' (2 chars)
12 => '7c' (2 chars) 13 => 'f7' (2 chars) 14 => '6f' (2 chars) 15 => '2f' (2 chars)
16 => '51' (2 chars) 17 => '88' (2 chars)
现在您必须将每个条目转换为整数。由于结果不再那么大,您可以使用 base_convert 函数更改值的基础。基数是 16(十六进制),您必须将其改回 10。foreach 循环后的结果 $bytes
如下所示:
array(18 items)
0 => 214 (integer) 1 => 1 (integer) 2 => 0 (integer) 3 => 128 (integer)
4 => 189 (integer) 5 => 242 (integer) 6 => 111 (integer) 7 => 47 (integer)
8 => 191 (integer) 9 => 1 (integer) 10 => 0 (integer) 11 => 0 (integer)
12 => 124 (integer) 13 => 247 (integer) 14 => 111 (integer) 15 => 47 (integer)
16 => 81 (integer) 17 => 136 (integer)
现在您必须定义哪些字节负责每个结果。
$matchIdBytes = array_reverse(array_slice($bytes, 0, 8));
$reservationIdBytes = array_reverse(array_slice($bytes, 8, 8));
$portBytes = array_reverse(array_slice($bytes, 16, 2));
- 对于匹配 ID,您必须获取前 8 个条目并反转数组
- 对于预订 ID,您必须从第 8 个条目开始获取接下来的 8 个条目并反转数组
- 对于端口,您必须获取最后 2 个条目并反转数组
现在您必须 return 值
return [
'matchId' => $this->getResultFromBytes($matchIdBytes),
'reservationId' => $this->getResultFromBytes($reservationIdBytes),
'tvPort' => $this->getResultFromBytes($portBytes)
];
getResultFromBytes()
函数:
**
* @param array $bytes
* @return string
*/
public function getResultFromBytes(array $bytes): string
{
$chars = array_map("chr", $bytes);
$bin = implode($chars);
$hex = bin2hex($bin);
return gmp_strval($this->gmp_hexDec($hex));
}
/**
* @param $n
* @return string
*/
public function gmp_hexDec($n): string
{
$gmp = gmp_init(0);
$multi = gmp_init(1);
for ($i=strlen($n)-1;$i>=0;$i--,$multi=gmp_mul($multi, 16)) {
$gmp = gmp_add($gmp, gmp_mul($multi, hexdec($n[$i])));
}
return $gmp;
}
此致