java hash碰撞分析模拟

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29923439/article/details/77983606

for java:      

依靠相应语言的hashtable/hashmap实现过程(request多为此结构),当不同的key存入时如果hash值相等则以链表方式连接在前面。此漏洞利用碰撞相同的hash值得到一个长链表, 重新get时,map的计算过程会将时间复杂度巨增,原来一个简单的过程将变成一个很费cpu的过程。 常见的服务器会将用户post的数据保存在hashmap中. 而向hashmap中插入n对元素的时间复杂度大约是O(n), 但如果精心构造key使得每个key的hash值相同(也就是产生了碰撞),则时间复杂度会恶化到O(n^2),导致消耗大量的CPU时间.

模拟实现

public class Hash {

public static void main(String[] args) {

HashMap<App, String>hash=new HashMap<App, String>();
Long start=System.currentTimeMillis();
for (Integer i = 0; i < 65536 ; i++) {
App app=new App();
app.setId(100);
hash.put(app, i.toString());
}
App app2=new App();
app2.setId(100);
hash.get(app2);
Long end=System.currentTimeMillis();
System.out.println("第一种方式"+(end-start)/1000);//33

HashMap<App, String>hash2=new HashMap<App, String>();
Long start2=System.currentTimeMillis();
for (Integer i = 0; i < 65536 ; i++) {
App app=new App();
app.setId(i);
hash2.put(app, i.toString());
}
App app3=new App();
app3.setId(100);
hash2.get(app3);
Long end2=System.currentTimeMillis();
System.out.println("第2种方式"+(end2-start2)/1000);
}
}


结果:第一种方式138

第二种:0

---------------------------------------

public class App {
  
private Integer id;
    
    public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
    public boolean equals(Object obj) {
    // TODO Auto-generated method stub
    return super.equals(obj);
    }
    @Override
    public int hashCode() {
    // TODO Auto-generated method stub
    return id;
    }
}

------------------------------------------

查看源码

扫描二维码关注公众号,回复: 4053457 查看本文章

  final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;//node 存储值的数据结构
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;   // 初始化长度
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);//根据hash值计算值卡槽(值所在hashmap的位置)
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))  //hash值相同key地址相同 或key的值相等
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {        //p为hash值相等的链表最后一个元素
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }


hash碰撞出现的情景?
(1)一般会出现在大的数据情况之下
(2)hashcode的生成方法唯一性较弱(比如上面的人为的生产hashcode)


猜你喜欢

转载自blog.csdn.net/qq_29923439/article/details/77983606