TOC

哈希:数字摘要

开发时,有时候我们需要将任意字符串映射成一个数字或字符串,这就是哈希。

  • MD5 输出 16 字节,用 16 进制数表示的话,就是 32 个字符。
  • SHA1 输出 20 字节,用 16 进制数表示的话,就是 40 个字符。
  • SHA256 输出 32 字节,用 16 进制数表示的话,就是 64 个字符。

性能:内置的 hash 循环 100 万次大概 68ms,而 md5 大概是 270ms, sha1 254ms, sha256 260ms。
PS: 内置 hash 默认采用 siphash
PS: 内置的那几个哈希算法(fnv, siphash, djbx33a)应该都比较优秀,为什么没有暴露出来呢?

这些哈希方法说起来简单,但是数学证明却是十分复杂,甚至我看到资料说著名的 DJBX33A 算法为什么要要采用一个 Magic Number 33 至今没有一个可靠的解释。开发者也不太需要懂这些,又不是做计算机理论研究,也不是搞数学的,我们只管用就是了。

a = hashlib.md5(b'hello world')
a.hexdigest()
'5eb63bbbe01eeed093cb22bb8f5acdc3'
int.from_bytes(a.digest(), 'big')
125893641179230474042701625388361764291

a = hashlib.sha256(b'hello world')
a.hexdigest()
'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
int.from_bytes(a.digest(), 'big')
83814198383102558219731078260892729932246618004265700685467928187377105751529

附:哈希函数

  • 循环冗余校验 Cyclic redundancy checks (CRC)
  • cksum 命令
  • 校验和 Checksums
  • checksum 命令
  • 通用哈希 Universal hash function families
  • 非加密哈希 Non-cryptographic hash functions
  • FNV (Fowler–Noll–Vo)
  • DJBX33A (Daniel J. Bernstein, Times 33 with Addition), 与 LCG 方法类似 1
  • 密钥加密哈希 Keyed cryptographic hash functions
  • hmac
  • siphash
  • 非密钥加密哈希 Unkeyed cryptographic hash functions
  • md5
  • sha 系列

参考资料与拓展阅读


  1. DJBX33A

    //  Daniel J. Bernstein #1
    unsigned DJB1Hash(const char *Key, unsigned TableSize)
    {
    unsigned hash = 0;
    while (*Key)
    {
        hash *= 33;
        hash += *Key;
        Key++;
    }
    return hash % TableSize;
    }
    //  Daniel J. Bernstein  #2
    unsigned DJB2Hash(const char *Key, unsigned TableSize)
    {
    unsigned hash = 5381;
    while (*Key)
    {
        hash <<= 5;
        hash += hash;
        hash += *Key;
        Key++;
    }
    return hash % TableSize;
    }