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

标签 c# php encryption hash

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

  • 哈希用户名(到字节数组)
  • 散列密码(成字节数组)
  • 连接用户名 + 密码哈希值(成两倍长的字节数组)
  • 哈希结果得到key(返回256位长度)
  • 用 key 逐字节异或文件得到加密文件

我不确定如何在 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() 返回的 hexits 转换为字节数组?”其次“我将如何散列那些字节数组?” (推论“将字节数组转换回十六进制字符串并对其进行散列就足够了吗?”)

最佳答案

与字符串编码为 Unicode 序列的 .NET 不同,PHP 的字符串是字节的哑序列——所以本质上,它们已经字节数组。因此,在 PHP 方面,您可以使用字符串完成所需的一切,根本不需要涉及数组,这反过来意味着不需要 unpack

要处理的主要事情是 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;
}

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

关于c# - 不确定如何将 C# 加密函数移植到 PHP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19242821/

相关文章:

php - 对图像的宽度和高度执行检查

ios - 使用 SecItemCopyMatching swift 2.0 导出由 SecKeyGeneratePair 生成的公钥

c# - 有没有办法在 ASP.NET MVC 3 RC2 中禁用 JSON ModelBinder?

c# - CallBase = true 最小起订量

php - SOAP 已安装但未在 phpinfo 中显示

php - 将键附加到现有数组值

c# - 在不指定 T 的情况下调用字符串 GenericMethod<T>()

c# - 默认页面无法正常工作

c# - 使用带有外部 Azure KeyVault (HSM) key 的 BouncyCaSTLe 创建证书时签名无效

java - JPA:在@Query 中使用 AttributeConverter