群人各说什么是哈希算法?
這個(gè)HASH算法不是大學(xué)里數(shù)據(jù)結(jié)構(gòu)課里那個(gè)HASH表的算法。這里的HASH算法是密碼學(xué)的基礎(chǔ),比較常用的有MD5和SHA,最重要的兩條性質(zhì),就是不可逆和無沖突。
所謂不可逆,就是當(dāng)你知道x的HASH值,無法求出x;
所謂無沖突,就是當(dāng)你知道x,無法求出一個(gè)y, 使x與y的HASH值相同。
這兩條性質(zhì)在數(shù)學(xué)上都是不成立的。因?yàn)橐粋€(gè)函數(shù)必然可逆,且由于HASH函數(shù)的值域有限,理論上會有無窮多個(gè)不同的原始值,它們的hash值都相同。MD5和SHA做到的,是求逆和求沖突在計(jì)算上不可能,也就是正向計(jì)算很容易,而反向計(jì)算即使窮盡人類所有的計(jì)算資源都做不到。
我覺得密碼學(xué)的幾個(gè)算法(HASH、對稱加密、公私鑰)是計(jì)算機(jī)科學(xué)領(lǐng)域最偉大的發(fā)明之一,它授予了弱小的個(gè)人在強(qiáng)權(quán)面前信息的安全(而且是絕對的安全)。舉個(gè)例子,只要你一直使用https與國外站點(diǎn)通訊,并注意對方的公鑰沒有被篡改,G**W可以斷開你的連接,但它永遠(yuǎn)不可能知道你們的傳輸內(nèi)容是什么。
順便說一下,王小云教授曾經(jīng)成功制造出MD5的碰撞,即md5(a) = md5(b)。這樣的碰撞只能隨機(jī)生成,并不能根據(jù)一個(gè)已知的a求出b(即并沒有破壞MD5的無沖突特性)。但這已經(jīng)讓他聲名大噪了。————————————————————————————————————————————————
哈希算法是用來解決數(shù)據(jù)和數(shù)據(jù)之間對應(yīng)關(guān)系的一種算法。它的初衷是用來加速數(shù)據(jù)存取。
計(jì)算機(jī)領(lǐng)域內(nèi)的大多數(shù)查找算法都與存儲數(shù)據(jù)的規(guī)模呈正相關(guān),用于衡量查找算法效率的量我們稱為平均查找長度,一般情況下,比較優(yōu)秀的查找算法的平均查找長度也不會短于數(shù)據(jù)規(guī)模以2為底的對數(shù)()。
哈希算法中,我們把數(shù)據(jù)項(xiàng)中的關(guān)鍵字用一種特定的對應(yīng)關(guān)系和存儲數(shù)據(jù)項(xiàng)的地址或地址偏移量對應(yīng)起來。注意:這種對應(yīng)一般不是一一對應(yīng),因?yàn)椴豢赡苡凶銐蚨嗟牡刂穼?yīng)近乎無窮多的關(guān)鍵字。
這樣一來,當(dāng)我們知道數(shù)據(jù)關(guān)鍵字的時(shí)候,在大多數(shù)情況下可以在常數(shù)時(shí)間(與數(shù)據(jù)規(guī)模無關(guān)的常數(shù))內(nèi)存取這個(gè)關(guān)鍵字。其他的時(shí)候,有可能發(fā)生多個(gè)關(guān)鍵字占據(jù)同一地址的現(xiàn)象,我們稱之為碰撞。
碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個(gè)具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))
這種情況下需要對關(guān)鍵字進(jìn)行二次或更多次的處理(如果發(fā)生多次碰撞),所費(fèi)時(shí)間在最差情況下也只與規(guī)模成正比。
只要這種函數(shù)的對應(yīng)關(guān)系取得足夠好,碰撞就會較少的發(fā)生,從而使平均查找長度在數(shù)據(jù)規(guī)模可控的情況下大幅度縮短,從而提高查找效率。
-----------------------------------------------------------------
哈希函數(shù)除此以外,也可以用來對廣義上的字符串(例如文本、視頻、圖片、程序等等等等)進(jìn)行特征驗(yàn)證。常見的有CRC32(32位循環(huán)冗余校驗(yàn)),從MD2、MD3、MD4發(fā)展而來的MD5(消息摘要算法第五版),SHA1(安全哈希算法)等等。
這類哈希算法的最初用途僅僅是對這些廣義字符串進(jìn)行完整性校驗(yàn),因?yàn)樵趥鬏斨袚p壞的比特位往往僅僅是極少數(shù),這些少數(shù)的錯(cuò)誤用上述提到的算法可以得出和原本正確文件截然不同的值,這也就使得文件完整性校驗(yàn)的開銷得以縮小。
-----------------------------------------------------------------
問題中描述的用途其實(shí)并不完全適當(dāng),但是在一定程度內(nèi)可行。
因?yàn)樵L問的網(wǎng)絡(luò)地址有無窮多個(gè),但是所有的哈希算法生成的特征值都有限,在極端情況下,很有可能會出現(xiàn)兩個(gè)不同的網(wǎng)絡(luò)地址具有相同特征值的情況。
這不僅使得在得知特征值時(shí),反向推測網(wǎng)絡(luò)地址具有了可行性(雖然開銷可能極大,需要大量時(shí)間窮舉),而且在網(wǎng)絡(luò)地址增長速度極快的今天,安全地址可能和危險(xiǎn)地址發(fā)生碰撞導(dǎo)致誤殺或者錯(cuò)誤放行的情況(現(xiàn)在雖然可能還沒出現(xiàn)過,但不能排除這種可能性)。
這種哈希算法本身雖然在理論上是不可逆的,但是它的思想保證了它也不是絕對可靠的。 ——————————————————————————————————————————————————
這種函數(shù)是一種摘要算法,你給他輸入一個(gè)任意長的數(shù)據(jù)A他給你返回固定長度的數(shù)據(jù)B,也稱B為“指紋”。
所以理論上來說你拿到一個(gè)B你是猜不出來A是什么的。因?yàn)锽是固定長度的,它對應(yīng)了無數(shù)個(gè)A。
舉個(gè)更形象點(diǎn)的例子。
這東西其實(shí)就像字典(其實(shí)就是)。你給出來的字符串是一個(gè)單詞,他在字典里面所屬的條目是A-Z其中一個(gè)字母。不管你給的單詞有多長,他總屬于字典中某一個(gè)目錄下(也就是首字母。。)。你現(xiàn)在有兩個(gè)單詞,你不知道他們都是什么,但是你知道一個(gè)在“A”里面一個(gè)在“E”里面。這樣你就知道這倆肯定不是同樣的單詞。不過由于每個(gè)條目下都有一大堆的單詞,所以你還是不知道這兩個(gè)單詞具體是什么。
當(dāng)然也有很大的概率兩個(gè)單詞都在E里面,這種情況叫做一種“碰撞”。兩個(gè)不同的東西生成了同樣的結(jié)果。拿到360的例子上來說就是,你開了家網(wǎng)站,起了個(gè)特別詭異的名字,用奇虎的哈希算法算出來的結(jié)果和某個(gè)不良網(wǎng)站一樣。那么你的網(wǎng)站就被當(dāng)不良網(wǎng)站屏蔽掉了。
一個(gè)好的哈希算法要保證盡可能的少產(chǎn)生碰撞。還是說你之前查字典的例子。這次你把字典拆了。給里面每個(gè)首字母下面又加了26個(gè)條目,分別是A-Z,里面裝著以這些當(dāng)結(jié)尾的單詞。這樣你隨便挑兩個(gè)單詞是一個(gè)坑里出來的概率就小多了。
設(shè)計(jì)一個(gè)哈希算法要考慮的有很多。比如你不知道一個(gè)單詞具體是什么,但知道首字母是A,但是你也不知道首字母A的單詞都是什么,你得找一堆單詞挨個(gè)試。要是算法復(fù)雜點(diǎn)你得試個(gè)幾十年才能找到符合條件的單詞,雖然可能不是你原來找的那個(gè),但是看起來差不多。那么這算法就成功了。人家拖了你幾十年。
然后突然你有一天覺醒了。感覺就差倆單詞太費(fèi)勁了。所以你買了本空字典,把天下單詞挨個(gè)試一遍,終于把所有目錄里面都填滿了。然后你以后找單詞就很方便了。別人給你一個(gè)單詞首字母是A,你就隨便從A里面找個(gè)應(yīng)附上。雖然不知道是不是他說的那個(gè),但至少看起來是一個(gè)坑里出來的就過關(guān)了。這字典就叫彩虹表。這東西寫起來比較耗時(shí)。沒準(zhǔn)你算了二十年發(fā)現(xiàn)試過的那些單詞首字母全是XYZ,但是人家每次給的都是ETA,那之前的活都白干了。
雖然這種方法得到的不是原始記錄,而僅僅是與之具有相同特征的記錄。而且有這個(gè)特征的記錄可能有一大堆。有的時(shí)候你碰巧拿到的就是原來的那個(gè),但大多數(shù)拿到的都是垃圾。如果你的表很全的話,那很有可能一堆記錄里面有個(gè)和原來的那條一模一樣的。這時(shí)候你可以根據(jù)別的什么信息猜猜找的是什么。比如你倆正打架,然后找出來他給你的單詞是F開頭的,那基本上就能猜出來了。
這就是哈希算法。一個(gè)好的哈希算法僅僅知道結(jié)果的話是極難反算出原始數(shù)據(jù)來的,特別是有意義的原始數(shù)據(jù)。
至于周老板怎么用我倒是不知道。不過他既然知道那些網(wǎng)址是非法的,那么肯定得有個(gè)小本,記錄著誰都干過壞事。然后想想之前的彩虹表(你懂的)。————————————————————————————————————————————————
就是空間映射函數(shù),例如,全體的長整數(shù)的取值作為一個(gè)取值空間,映射到全部的字節(jié)整數(shù)的取值的空間,這個(gè)映射函數(shù)就是HASH函數(shù)。通常這種映射函數(shù)是從一個(gè)非常大的取值空間映射到一個(gè)非常小的取值空間,由于不是一對一的映射,HASH函數(shù)轉(zhuǎn)換后不可逆,即不可能通過逆操作和HASH值還原出原始的值,受到計(jì)算能力限制(注意,不是邏輯上不可能,前面的不可能是邏輯上的)而且也無法還原出所有可能的全部原始值。HASH函數(shù)運(yùn)用在字典表等需要快速查找的數(shù)據(jù)結(jié)構(gòu)中,他的計(jì)算復(fù)雜度幾乎是O(1),不會隨著數(shù)據(jù)量增加而增加。另外一種用途就是文件簽名,文件內(nèi)容很多,將文件內(nèi)容通過HASH函數(shù)處理后得到一個(gè)HASH值,驗(yàn)證這個(gè)文件是否被修改過,只需要把文件內(nèi)容用同樣的HASH函數(shù)處理后得到HASH值再比對和文件一起傳送的HASH值即可,如不公開HASH算法,那么信道是無法篡改文件內(nèi)容的時(shí)候篡改文件HASH值,一般應(yīng)用的時(shí)候,HASH算法是公開的,這時(shí)候會用一個(gè)非對稱加密算法加密一下這個(gè)HASH值,這樣即便能夠計(jì)算HASH值,但沒有加密密鑰依然無法篡改加密后HASH值。這種算法用途很廣泛,用在電子簽名中。HASH算法也可進(jìn)行破解,這種破解不是傳統(tǒng)意義上的解密,而是按照已有的HASH值構(gòu)造出能夠計(jì)算出相同HASH值的其他原文,從而妨礙原文的不可篡改性的驗(yàn)證,俗稱找碰撞。這種碰撞對現(xiàn)有的電子簽名危害并不嚴(yán)重,主要是要能夠構(gòu)造出有意義的原文才有價(jià)值,否則就是構(gòu)造了一個(gè)完全不可識別的原文罷了,接收系統(tǒng)要么無法處理報(bào)錯(cuò),要么人工處理的時(shí)候發(fā)現(xiàn)完全不可讀。理論上我們終于找到了在可計(jì)算時(shí)間內(nèi)發(fā)現(xiàn)碰撞的算法,推算了HASH算法的逆操作的時(shí)間復(fù)雜度大概的范圍。
HASH算法的另外一個(gè)很廣泛的用途,就是很多程序員都會使用的在數(shù)據(jù)庫中保存用戶密碼的算法,通常不會直接保存用戶密碼(這樣DBA就能看到用戶密碼啦,好危險(xiǎn)啊),而是保存密碼的HASH值,驗(yàn)證的時(shí)候,用相同的HASH函數(shù)計(jì)算用戶輸入的密碼得到計(jì)算HASH值然后比對數(shù)據(jù)庫中存儲的HASH值是否一致,從而完成驗(yàn)證。由于用戶的密碼的一樣的可能性是很高的,防止DBA猜測用戶密碼,我們還會用一種俗稱“撒鹽”的過程,就是計(jì)算密碼的HASH值之前,把密碼和另外一個(gè)會比較發(fā)散的數(shù)據(jù)拼接,通常我們會用用戶創(chuàng)建時(shí)間的毫秒部分。這樣計(jì)算的HASH值不大會都是一樣的,會很發(fā)散。最后,作為一個(gè)老程序員,我會把用戶的HASH值保存好,然后把我自己密碼的HASH值保存到數(shù)據(jù)庫里面,然后用我自己的密碼和其他用戶的用戶名去登錄,然后再改回來解決我看不到用戶密碼而又要“偷窺”用戶的需要。最大的好處是,數(shù)據(jù)庫泄露后,得到用戶數(shù)據(jù)庫的黑客看著一大堆HASH值會翻白眼。
總結(jié)
以上是生活随笔為你收集整理的群人各说什么是哈希算法?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络电视机如何安装暴风影音软件
- 下一篇: HashMap和HashSet的内部工作