不确定如何将C#加密函数移植到PHP

我在C#中有一个基本的加密功能,用于加密和存储游戏的保存文件,该游戏使用用户的用户名和密码进行游戏的网站.最近我意识到,如果用户要更改密码,则会导致其保存无法访问,因为它使用旧密码加密.所以,我正在尝试构建一个
PHP函数,以便在更新密码时“重新转换”它们的保存.不幸的是,问题在于C#使用字节数组来执行散列,而PHP使用字符串,我不确定如何协调这两者.这是一般过程:

>哈希用户名(进入字节数组)
>哈希密码(进入字节数组)
>连接用户名密码哈希值(成为两倍长的字节数组)
>哈希结果获取密钥(返回256位长度)
> xor文件逐字节,带有密钥以获取加密文件

我不确定如何在PHP中实现这一点.我最初尝试使用unpack(‘C *’,hash(“sha256”,$thing_to_be_hashed,false))但这似乎没有产生正确的字节数组.然后我尝试了这个:

$new_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $newpass, false), false);
$old_key = hash("sha256", hash("sha256", $username, false) . hash("sha256", $oldpass, false), false);

$conversion_key = array();
for($i = 0; $i < strlen($new_key); ++$i) {
    $conversion_key[] = $old_key[$i] ^ $new_key[$i]; 
    // this part with the array is a bit wonky, I know, but it didn't seem like
    // it would have worked anyway since I was xor'ing things like 'f' and '3'
    // instead of bytes like '23' and '57'.
}
$file_contents = file_get_contents("savefile.sav");
for($i = 0; $i < strlen($file_contents); ++$i) {
    $file_contents[$i] = $file_contents[$i] ^ $conversion_key[$i % count($conversion_key)]; // I read somewhere I can access $file_contents like this to get bytes
}

不幸的是,在任何阶段,这两种方法都不起作用(前一个解包方法即使在第一阶段的散列中也没有产生正确的字节数组,也不确定我是否正确地将它们放回到第二阶段的字符串中).非常感谢我能得到的任何帮助.谢谢!

编辑:我发生unpack()不会给我正确的字节数组,因为它字面上解码字符串;所以我想我的主要问题首先是“如何将hash()返回的十六进制转换为字节数组?”其次“我将如何对这些字节数组进行散列?” (有推论“将字节数组转换回六角形字符串并散列那些就足够了吗?”)

最佳答案 与.NET编码Unicode序列的.NET不同,PHP的字符串是字节的哑序 – 所以本质上它们已经是字节数组.因此,在PHP方面,您可以使用字符串完成所有操作,并且根本不需要涉及数组,这反过来意味着不需要解压缩.

要处理的主要问题是PHP哈希函数默认返回十六进制编码而不是直接二进制输出.从一个转换到另一个很容易:使用hex2bin,但是将第三个(可选)参数设置为true也更容易.

所以你可以得到你需要的哈希:

// for convenience
function sha256($data) {
    return hash("sha256", $data, true);
}

$new_key = sha256(sha256($username).sha256($newpass));
$old_key = sha256(sha256($username).sha256($oldpass));

然后,此函数将对两个键进行异或:

function str_xor($str1, $str2) {
    if (strlen($str1) != strlen($str2)) {
        return false;
    }

    $len = strlen($str1);
    for($i=0; $i < $len; $i++) {
        $str1[$i] = $str1[$i] ^ $str2[$i];
    }

    return $str1;
}

因此,您可以使用现有循环将保存的数据从一个密钥“重新加密”到另一个密钥.

点赞