【问题标题】:Cannot get same hash in C# as in python无法在 C# 中获得与 python 中相同的哈希值
【发布时间】:2017-10-24 09:19:07
【问题描述】:

我有一个字符串需要散列才能访问 API。 API-creator 在 Python 中提供了一个 coden-p,它对代码进行哈希处理,如下所示:

hashed_string = hashlib.sha1(string_to_hash).hexdigest()

当使用这个散列字符串访问 API 时,一切都很好。我试图在 C# 中获得相同的散列字符串结果,但没有成功。我尝试了很多令人难以置信的方法,但到目前为止没有任何效果。我也知道 hexdigest 部分,并且在尝试模仿行为时我一直牢记这一点。

有人知道如何在 C# 中获得相同的结果吗?

编辑: 这是我尝试在 C# 中重现相同结果的众多方法之一:

public string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            sb.Append(b.ToString("X2"));
        }

        return sb.ToString().ToLower();
    }
}

此代码取自:Hashing with SHA1 Algorithm in C#

另一种方式

public string ToHexString(string myString)
{
    HMACSHA1 hmSha1 = new HMACSHA1();
    Byte[] hashMe = new ASCIIEncoding().GetBytes(myString);
    Byte[] hmBytes = hmSha1.ComputeHash(hashMe);
    StringBuilder hex = new StringBuilder(hmBytes.Length * 2);
    foreach (byte b in hmBytes)
    {
        hex.AppendFormat("{0:x2}", b);
    }
    return hex.ToString();
}

此代码取自:Python hmac and C# hmac

编辑 2

一些输入/输出:

C#(使用上面描述的第二种方法)

输入:callerId1495610997apiKey3*_&E#N@B1)O)-1Y

输出:1ecded2b66e152f0965adb96727d96b8f5db588a


Python

输入:callerId1495610997apiKey3*_&E#N@B1)O)-1Y

输出:bf11a12bbac84737a39152048e299fa54710d24e


C#(使用上面描述的第一种方法)

输入:callerId1495611935​apiKey{[B{+%P)s;WD5&5x

输出:7e81e0d40ff83faf1173394930443654a2b39cb3


Python

输入:callerId1495611935​apiKey{[B{+%P)s;WD5&5x

输出:512158bbdbc78b1f25f67e963fefdc8b6cbcd741

【问题讨论】:

  • 请出示minimal reproducible example - 我猜您的 C# 代码中存在错误,但由于我们看不到您的任何 C# 代码,因此很难判断。
  • 完成! @JonSkeet
  • 你没有费心包括你的first C#代码的结果,这和你的python结果一样,只是大写......
  • 正如 cmets 在 Federico 的回答中所指出的,您在底部两个示例的输入中有一个非 ascii 字符。我怀疑那不应该在那里,是吗?
  • 请注意,如果您从一开始就提供了minimal reproducible example,那么您很可能在点击“发布”之前就已经发现了问题。值得下次记住...

标签: c# python hash sha1


【解决方案1】:

C#:

public static string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            sb.Append(b.ToString("x2")); // x2 is lowercase
        }

        return sb.ToString().ToLower();
    }
}

public static void Main()
{
    var x  ="callerId1495611935​apiKey{[B{+%P)s;WD5&5x";
    Console.WriteLine(Hash(x)); // prints 7e81e0d40ff83faf1173394930443654a2b39cb3
}

Python

import hashlib
s = u'callerId1495611935​apiKey{[B{+%P)s;WD5&5x'
enc = s.encode('utf-8') # encode in utf8
hash = hashlib.sha1(enc)
formatted = h.hexdigest()
print(formatted) # prints 7e81e0d40ff83faf1173394930443654a2b39cb3

您的主要问题是您在 C# 和 Python 中对同一字符串使用不同的编码。在两种语言中使用 UTF8 并使用相同的大小写。输出是一样的。

注意在您的输入字符串中(在callerId1495611935apiKey{[B{+%P)s;WD5&5x 之间)有一个隐藏\u200b character。这就是为什么用 UTF-8 编码字符串会产生与使用 ASCII 编码不同的结果的原因。该字符是否必须在您的字符串中?

【讨论】:

  • 我一般都是为了明确,但至少在我的盒子上没有区别(这是我所期望的,因为输入是全ASCII)。 hashlib.sha1(s).hexdigest() 给出相同的结果。
  • @JonSkeet 如果您尝试复制和粘贴 OP 原始输入字符串,您会注意到在 callerId1495611935apiKey{[B{+%P)s;WD5&5x 之间有一个隐藏的 \u200b 字符(不要问我为什么) .
  • 呃——很好看。这将解释事情。我怀疑不应该在输入中。
  • @JonSkeet 我同意。
  • 非常感谢,非常好!也感谢 JonSkeet 的帮助,我会尽力解决这个问题。 :)
猜你喜欢
  • 2020-02-06
  • 2017-01-24
  • 2018-11-27
  • 2015-01-04
  • 2012-01-17
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2015-07-11
相关资源
最近更新 更多