【问题标题】:Computing hash string of specific length from seed string从种子字符串计算特定长度的哈希字符串
【发布时间】:2020-11-18 19:45:55
【问题描述】:

什么是从字符串种子计算(不安全)哈希字符串的简单方法,最终结果具有特定长度和相当低的冲突概率?

例如在 C# 中:

string seed = "PK_DELETE_THIS_TABLE";  
Console.WriteLine("Seed: {0}", seed);  
string hashedData = SimpleHash(seed, 30/2);  
Console.WriteLine("Hash: {0}", hashedData); 

结果:

Seed: PK_DELETE_THIS_TABLE
Hash: CC598675A3072C8B1768DED09BAAA5

【问题讨论】:

  • 您是否有特殊原因要推出自己的哈希算法?
  • 关于正确执行自己的散列、加密、日期时间处理(可能还有更多)实现的规则 #1:DON'T - 除非您完全是专家。使用已经大量存在的工具
  • 唯一的原因是我需要一个特定长度的哈希字符串。对于我的用例来说,安全性并不那么重要,而且碰撞问题也很低;我需要将名称转换为 30 个字符的哈希字符串。

标签: c# hash


【解决方案1】:

我们可以用以下算法计算出碰撞概率相当低的不安全哈希:

public string SimpleHash(string seed, int halfHashLength)  
{  
    if(seed == null) throw new ArgumentNullException(nameof(seed));
    if(halfHashLength <= 0) throw new ArgumentException("Value should be larger than 0.", nameof(halfHashLength));
    
    // Use different random algo for more deterministic hash:
    // https://stackoverflow.com/questions/17094189/crossplatform-random-number-generator
    Random rnd = new Random(seed.GetHashCode());
    byte[] tmp = new byte[halfHashLength];
    rnd.NextBytes(tmp);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < tmp.Length; i++)
    {
        sb.Append(tmp[i].ToString("X2"));
    }
    return sb.ToString();
}

请注意,上面计算的哈希可能无法跨运行时移植,甚至可能在运行时重新启动之间也不能移植(.NET Core 将在每次重新启动运行时时返回不同的 seed.GetHashCode())。如果这是一个问题,请使用更具确定性的哈希算法。

【讨论】:

  • 注意GetHashCode 不是规范的一部分,它依赖于它的实现,不能保证它们在其他平台和实现等 上是相同的,如果没有的话不要打扰你(它可能不会),那么这实际上是一个很好的答案
  • 注意字节数组转换可以简化为BitConverter.ToString(tmp).Replace("-","")
  • @TheGeneral 更新了答案以说明您的评论。
猜你喜欢
  • 2012-07-12
  • 2014-06-18
  • 1970-01-01
  • 2013-02-16
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
相关资源
最近更新 更多