开发时,有时候我们需要将任意字符串映射成一个数字或字符串,这就是哈希。
- 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 系列
参考资料与拓展阅读
- StackOverflow, How to hash a string into 8 digits?
- 维基百科(en), List of hash functions
- 维基百科(en), Hash function
- 维基百科(en), Cryptographic hash function
- 维基百科(en), Secure Hash Algorithms
- 维基百科(en), Hash function security summary
- 维基百科(en), NIST hash function competition, 美国标准技术研究所(NIST)哈希函数竞赛
类似的活动: - StackOverflow, Reason for 5381 number in DJB hash function?
-
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; }