面试宝典系列-Hash碰撞是什么?

哈希表(或散列表),是将键名key按指定的散列函数HASH经过HASH(key)计算后映射到表中一个记录,而这个数组就是哈希表。这里的HASH指任意的函数,例如MD5、CRC32、SHA1或你自定义的函数实现。

理想情况下HashTable的性能是O(1)的,性能消耗主要集中在散列函数HASH(key),通过HASH(key)直接定位到表中的记录。
而在实际情况下经常会发生key1 != key2,但HASH(key1) = HASH(key2),这种情况即Hash碰撞问题,碰撞的概率越低HashTable的性能越好。当然Hash算法太过复杂也会影响HashTable性能(HashTable碰撞)

PHP数组中,键名可以为数字或字符串类型。而在内核中只允许数字索引,对于字符串索引,内核采用了time33算法将字符串转换为整型(是对字符串的每个字符转换为ASCII码乘上33并且相加得到的结果)

键名为数字时:内核中哈希表的散列函数就是简单的h & ht->nTableMask,其中h代表PHP中设置的索引号,nTableMask等于哈希表分配的长度-1。

键名为字符串时:与数字索引相比,只是多了一步将字符串转换为整型。用到的算法是time33

HashTable碰撞:PHP中使用一个叫Backet的结构体表示桶,同一哈希值的所有桶被组织为一个单链表。(先根据哈希值找到位置,然后再判断原始key是否相同,如果不相同,找单链表下一个元素)

PHP哈希表最小容量是8(2^3),最大容量是0×80000000(2^31),并向2的整数次幂圆整(即长度会自动扩展为2的整数次幂,如13个元素的哈希表长度为16;100个元素的哈希表长度为128)

防hashTable碰撞攻击(构造一个大数组,键值产生的哈希值都相同,然后post提交这个数组)在>=PHP5.3.9的版本中增加了一个配置项max_input_vars,用于标识一次http请求最大接收的参数个数,默认为1000。但如果是json方式提交,并不能防止攻击。

一般来说有两种方式,一是限制每个桶链表的最长长度;二是使用其它数据结构如红黑树取代链表组织碰撞哈希(并不解决哈希碰撞,只是减轻攻击影响,将N个数据的操作时间从O(N^2)降至O(NlogN),代价是普通情况下接近O(1)的操作均变为O(logN))

转载于:https://my.oschina.net/suyain/blog/1858745

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值