【问题标题】:Converting C# code to php encoding issue将 C# 代码转换为 php 编码问题
【发布时间】:2016-05-25 22:25:51
【问题描述】:

我尝试在 php 中复制此 C#code 以获得相同的输出(我无法仅更改 c# 代码 php)。而我被卡住了

 public static string HashData(string textToBeEncripted)
         {
        //Convert the string to a byte array
        Byte[] byteDataToHash =              System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);

        //Compute the MD5 hash algorithm
        Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);

        return System.Text.Encoding.Unicode.GetString(byteHashValue);
    }

我到现在做的php代码是这样的

$a = "test";
$a = mb_convert_encoding($a, "UTF-16LE");

$a = md5($a,true);

$a = unpack('C*', $a);
var_dump($a);
//with the output
array(16) { [1]=> int(200) [2]=> int(5) [3]=> int(158) [4]=> int(46) [5]=> int(199) [6]=> int(65) [7]=> int(159) [8]=> int(89) [9]=> int(14) [10]=> int(121) [11]=> int(215) [12]=> int(241) [13]=> int(183) [14]=> int(116) [15]=> int(191) [16]=> int(230) }

如您所见,输出与 C# code 中的相同 但我被困在函数 System.Text.Encoding.Unicode.GetString() 上。如何在 php 中复制它?或者有更简单的方法来获得相同的输出?(对不起,我无法更改 C# 代码)
编辑:基于 Vasiliy Zverev 的回答,因为 php 哈希值略有不同。我最终用 C# 哈希值近似 php 的哈希值

function validare_parola($parola,$dbHash){

$parola = mb_convert_encoding($parola, "UTF-16LE");
$parola = md5($parola, true);
$parola = mb_convert_encoding($parola, "UCS-2BE", "UCS-2LE");
$parola = bin2hex($parola);

$procent;
similar_text($dbHash,$parola,$procent);

if($procent>=90){
    return true;
}else{
    return false;
}

}

$parola = "testa";

$dbHash = "10095018710be2bcbbf9bba3f9d91ce8";
if(validare_parola($parola,$dbHash)){
echo 'PASSWORD CORRECT.You can log in.';
}else{
echo 'INCORRECT PASSWORD.Try again.';
}

作为旁注,不要使用 md5 作为密码,使用 php password hashing api

Edit2:我最终使用了 Vasiliy Zverev 解决方案。
Edit3: 对于值“111111”,php 中有不同的输出...
Edit4: Vasily Zverev 更新了他的解决方案,现在按预期工作

【问题讨论】:

标签: c# php


【解决方案1】:

解决方案,更新

$a = "SF0D9G9SGGF0gdsfg976590";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a, true);
$res = '';
for($i=0; $i<16; $i+=2) {
    // System.Text.Encoding.Unicode.GetString(byteHashValue) replaces invalid characters to 0xfffd ('я')
    // while PHP to 0x003d ('?') or empty string. So replace them like C# does
    $a2 = mb_convert_encoding($a[$i].$a[$i+1], "UTF-16LE","UTF-16LE"); // check if this is invalid UTF-16 character
    if(strlen($a2)==0 || $a[$i]!=$a2[0]) {
        // replace invalid UTF-16 character with C# like
        $v = 0xfffd;
    }
    else {
        // prepare a word (UTF-16 character)
        $v = ord($a[$i+1])<<8 | ord($a[$i]);
    }
    // print each word without leading zeros as C# code does
    $res .= sprintf("%x",$v);
}
echo($res);

【讨论】:

  • 该哈希的输入是什么?
  • 试试新版本 :) 我现在一个一个搜索无效的 UTF-16 字符。
  • 干得好。终于开始工作了。非常感谢您的帮助,真的很棒。
【解决方案2】:

删除了这个变体,因为它是错误的。请参阅上面的正确代码。

【讨论】:

  • 嗨,它适用于“测试”。但是如果我输入 $a="parolaeste" 我会在 php 端得到不同的输出。
  • 我想我知道出了什么问题:return System.Text.Encoding.Unicode.GetString(byteHashValue); 并非所有二进制字符串都会产生正确的 UTF-16 字符串。某些位组合无效。虽然 php bin2hex(md5()) 不做额外的 UTF 转换。我今天稍后会准备修复。
  • 请在另一个答案中试用我的新版本。
  • 如果我输入 $a="111111" 我在 php 中得到不同的输出,加号是 0。
  • 大声笑,这是因为hex += String.Format("{0:x2}", (uint) System.Convert.ToUInt32(tmp.ToString())) 吃了前导零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 2011-01-04
  • 2023-03-24
  • 2019-07-18
相关资源
最近更新 更多