【问题标题】:sha1 function giving a different result to equivalent .net codesha1 函数为等效的 .net 代码提供不同的结果
【发布时间】:2014-11-26 20:40:04
【问题描述】:

我有以下 PHP 代码:

$stringToHash = "10123456789"."2014:11:25-15:42:00"."20.00"."826"."sharedsecret";

echo($stringToHash);
// outputs:
// 101234567892014:11:25-15:42:0020.00826sharedsecret

$ascii = bin2hex($stringToHash);

echo($ascii);
// outputs:   
// 3130313233343536373839323031343a31313a32352d31353a34323a303032302e3030383236736861726564736563726574

$sha = sha1($ascii);

echo($sha);
// outputs:
// 847aa9da32c54ed8bb9183007336f5762a62ef20

这是等效的 C# 代码:

var stringToHash = "10123456789" + "2014:11:25-15:42:00" + "20.00" + "826" + "sharedsecret";

Console.WriteLine(stringToHash);
// outputs:
// 101234567892014:11:25-15:42:0020.00826sharedsecret

var bytes = Encoding.ASCII.GetBytes(stringToHash);

var hexString = BitConverter.ToString(bytes).Replace("-", string.Empty);

Console.WriteLine(hexString);
// outputs:
// 3130313233343536373839323031343A31313A32352D31353A34323A303032302E3030383236736861726564736563726574

SHA1 sha = new SHA1CryptoServiceProvider();
var password = sha.ComputeHash(bytes);
var result = BitConverter.ToString(password).ToLower().Replace("-", string.Empty);

Console.WriteLine(result);
// outputs:
// c8069048623d6b98a08454e43e1a02a42cf7d61d

var hexStringBytes = Encoding.ASCII.GetBytes(hexString);
var hexStringPassword = sha.ComputeHash(hexStringBytes);
var hexStringResult = BitConverter.ToString(hexStringPassword).ToLower().Replace("-", string.Empty);

Console.WriteLine(hexStringResult);
// outputs:
// bd857ca08446001f7182fbbbd41e747abe302a87

前两个输出是相同的。原始字符串是相同的,转换后的 ASCII 十六进制数组也是相同的,但是 PHP 中的 sha1() 给了我与 .net 的 SHA1CryptoServiceProvider 不同的结果。如果我将该输出转换为字符串并再次对其进行哈希处理,结果也会有所不同。

在 .net 中,对象必须采用字节数组的形式,然后才能从中创建 SHA 哈希,我不明白我需要转换为字节数组以产生与PHP 代码。

这是有问题的,因为我发布到的第三方服务使用 PHP 版本来验证他们端的对象,并且我的程序是用 .net 编写的。我可以用 PHP 编写一个中间人并通过它进行中继,但我真的不想这样做。

任何关于为什么两者给出不同结果的见解?谢谢

【问题讨论】:

  • 您忘记在 C# 程序中实际使用 hexString。我不明白你为什么要在散列之前使用十六进制字符串,但是你错过了 .net 中的那一步是问题所在。
  • hexstring 肯定只是十六进制字节数组的字符串表示形式吗?我正在使用字节数组,我只是将其转换为字符串以将其打印到控制台并查看它是否与该阶段的 PHP 等效项匹配。你是说我应该取那个字符串,将它转换回一个字节数组并散列它以获得与 PHP 相同的结果吗?至于为什么,这是第三方提供的示例代码,展示了他们如何计算哈希值,我正在尝试在 C# 中复制它。
  • 您正在转换 2 个不同的值。 PHP 转换十六进制,.net 不。
  • 有什么区别呢?我以为它们只是表示相同数据(base8/base16)的两种方式?那么在 C# 中对字节数组进行哈希处理就相当于在 php 中对十六进制数组进行哈希处理?
  • 以编程方式,这些值将是等效的。但不是在散列一些东西的计划中。散列“cat”的 ascii 值与散列二进制等效项不同。

标签: c# php .net sha1


【解决方案1】:

这样就可以了。受到post 和我 2 天前遇到但找不到的问题的启发。

public string HashItThePHPWay(string hashMe)
        {
            var sha = new SHA1CryptoServiceProvider();
            string b64 = ByteArrayToString(Encoding.ASCII.GetBytes(hashMe));
            var b64Bytes = Encoding.ASCII.GetBytes(b64);
            var result = sha.ComputeHash(b64Bytes);
            return BitConverter.ToString(result).Replace("-", "").ToLower();
        }

    public static string ByteArrayToString(byte[] ba)
    {
        StringBuilder hex = new StringBuilder(ba.Length * 2);
        foreach (byte b in ba)
        {
            hex.AppendFormat("{0:x2}", b);
        }
        return hex.ToString().ToLower();
    }

【讨论】:

  • 真正的诀窍是在获取 ASCII 编码之前从 b64 字符串中删除破折号
  • 非常感谢,这让我很难过
  • 我可以知道你为什么在两个不同的地方同时使用BitConverter.ToString(result).Replace("-", "").ToLower()ByteArrayToString(..) 函数,因为它们给出了相同的结果?
猜你喜欢
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 2011-11-28
相关资源
最近更新 更多