漫話:如何給女友解釋爲何12306會用戶信息泄露(上)——密碼篇

某天下午,我正在公司愉快的擼代碼,忽然來了一個電話。原來是女友打來的。git

掛斷電話後,我趕忙登陸12306改掉了個人密碼,還好我各個網站的密碼不同,這樣就能很好的避免被撞庫了。github

下班後,回到家中,女友第一時間過來找我,必定要我給他解釋一下12306的數據泄露背後的知識。算法

明文密碼

明文密碼就是直接能夠看懂的,好比123456admin等等,而不是通過加密顯示出****的內容,這種叫作暗碼。好比abc表明123,若是告訴你abc而不告訴你解碼規則,你就不能翻譯出真正的密碼123數據庫

不少網站都有註冊登陸功能,對於用戶在註冊的時候,填寫的用戶名和密碼,若是不通過任何處理直接保存到數據庫中,這種狀況下,保存的就是用戶的明文密碼。編程

這樣直接把用戶的明文密碼保存下來,對於程序開發來講是很方便的。用戶在登陸的時候直接到數據庫中進行帳號密碼匹配就能夠了。可是,同時也埋下了很大的隱患,一旦數據庫信息泄露,那麼黑客就能夠拿到全部用戶的用戶名和密碼。安全

舉個例子,好比用戶的明文密碼是helloworld,加密後的密文是xxeerrqqbash

用戶註冊:dom

helloworld -> 加密 -> xxeerrqq -> 保存xxeerrqq到數據庫中
複製代碼

用戶登陸函數

helloworld -> 加密 -> xxeerrqq -> 使用xxeerrqq到數據庫中匹配密碼
複製代碼

密碼加密技術通過不少年的發展,已經有了不少成熟的方案,這裏就簡單介紹幾個。工具

對稱加密

對稱加密,指的是須要對加密和解密使用相同密鑰的加密算法。

最簡單的對稱加密算法就是經過ASCII碼的變化進行密碼保存,好比把abcde轉換成bcdef,其加密算法就是把ASCII碼增長1 。

這種加密算法,有一個特色,就是能夠根據加密後獲得的密文,再根據密鑰還原出明文。


可是,這種算法已經不多有網站在用了,雖然如今有不少方法能夠把密鑰單獨保存,可是,既然黑客能夠破解網站拿到用戶的密文,就有可能也能獲取到密鑰。

在對稱加密算法中經常使用的算法有:DES、3DES、TDEA、Blowfish、RC二、RC四、RC五、IDEA、SKIPJACK等。

單向Hash算法

單向散列算法,又稱hash函數,就是把任意長的輸入消息串變化成固定長的輸出串的一種函數。通常用於產生消息摘要,密鑰加密等。

單向Hash算法是一種沒法經過計算還原出原始密碼,並且實現比較簡單的算法。


不少互聯網公司都採用這種方式保存用戶密碼,曾經這種方式也是比較安全的方式。

常見散列函數(Hash函數)有: MD5(Message Digest Algorithm 5)、 SHA(Secure Hash Algorithm)、 MAC(Message Authentication Code)、 CRC(Cyclic Redundancy Check)

彩虹表

彩虹表(rainbow table)是一個用於加密散列函數逆運算的預先計算好的表,經常使用於破解加密過的密碼散列。 查找表經常用於包含有限字符固定長度純文本密碼的加密。這是以空間換時間的典型實踐,在每一次嘗試都計算的暴力破解中使用更少的計算能力和更多的儲存空間,但卻比簡單的每一個輸入一條散列的翻查表使用更少的儲存空間和更多的計算性能。

一般狀況下,當字段通過散列處理(如MD5),會生成一段散列值,而散列後的值通常是沒法經過特定算法獲得原始字段的。可是某些狀況,好比一個大型的彩虹表,經過在表中搜索該MD5值,頗有可能在極短的時間內找到該散列值對應的真實字段內容。

加鹽Hash算法

鹽(Salt),在密碼學中,是指在散列以前將散列內容(例如:密碼)的任意固定位置插入特定的字符串。這個在散列中加入字符串的方式稱爲「加鹽」。其做用是讓加鹽後的散列結果和沒有加鹽的結果不相同,在不一樣的應用情景中,這個處理能夠增長額外的安全性。

加鹽後的散列值,能夠極大的下降因爲用戶數據被盜而帶來的密碼泄漏風險,即便經過彩虹表尋找到了散列後的數值所對應的原始內容,可是因爲通過了加鹽,插入的字符串擾亂了真正的密碼,使得得到真實密碼的機率大大下降。


對於加了「固定鹽」的Hash算法,須要保護「鹽」不能泄露,這就會遇到「保護對稱密鑰」同樣的問題,一旦「鹽」泄露,根據「鹽」從新創建彩虹表能夠進行破解。

PBKDF2算法

PBKDF2算法,即Password-Based Key Derivation Function 2。PBKDF2簡單而言就是將加鹽Hash進行屢次重複計算,這個次數是可選擇的。

該算法原理大體至關於在Hash算法基礎上增長隨機鹽,並進行屢次Hash運算,隨機鹽使得彩虹表的建表難度大幅增長,而屢次Hash也使得建表和破解的難度都大幅增長。

若是計算一次所須要的時間是1微秒,那麼計算1百萬次就須要1秒鐘。假如攻擊一個密碼所需的彩虹表有1千萬條,創建所對應的彩虹表所須要的時間就是115天。這個代價足以讓大部分的攻擊者忘而生畏。


美國政府機構已經將這個方法標準化,而且用於一些政府和軍方的系統。 這個方案最大的優勢是標準化,實現容易同時採用了久經考驗的SHA算法。

還有不少算法也能夠有效抵禦彩虹表,常見的有bcrypt、scrypt等。

bcrypt

bcrypt是專門爲密碼存儲而設計的算法,基於Blowfish加密算法變形而來,由Niels Provos和David Mazières發表於1999年的USENIX。

實現中bcrypt會使用一個加鹽的流程以防護彩虹表攻擊,同時bcrypt仍是適應性函數,它能夠藉由增長迭代之次數來抵禦日益增進的計算機運算能力透過暴力法破解。

由bcrypt加密的文件可在全部支持的操做系統和處理器上進行轉移。它的口令必須是8至56個字符,並將在內部被轉化爲448位的密鑰。然而,所提供的全部字符都具備十分重要的意義。密碼越強大,您的數據就越安全。

bcrypt通過了不少安全專家的仔細分析,使用在以安全著稱的OpenBSD中,通常認爲它比PBKDF2更能承受隨着計算能力增強而帶來的風險。bcrypt也有普遍的函數庫支持,所以建議使用這種方式存儲密碼。

Java中使用bcrypt

能夠在官網(http://www.mindrot.org/projects/jBCrypt/ )獲取該算法的源代碼。在Java中,能夠直接使用如下方式進行加密:

public static void main(String[] args) throws NoSuchAlgorithmException

{
    String  originalPassword = "漫話編程";
    String generatedSecuredPasswordHash = BCrypt.hashpw(originalPassword, BCrypt.gensalt(12));
    System.out.println(generatedSecuredPasswordHash);

    boolean matched = BCrypt.checkpw(originalPassword, generatedSecuredPasswordHash);

    System.out.println(matched);

}
複製代碼

scrypt

scrypt是由著名的FreeBSD黑客 Colin Percival爲他的備份服務 Tarsnap開發的。

設計時考慮到大規模的客制硬件攻擊而刻意設計須要大量內存運算。scrypt須要使用大量內存的緣由來自於產生大量僞隨機性(英語:pseudorandom)資料做爲算法計算的基礎。一旦這些資料被產生後,算法將會以僞隨機性的順序讀取這些資料產生結果。所以最直接的實作方式將會須要大量內存將這些資料儲存在內存內供算法計算。

scrypt不只計算所需時間長,並且佔用的內存也多,使得並行計算多個摘要異常困難,所以利用彩虹表進行暴力攻擊更加困難。scrypt沒有在生產環境中大規模應用,而且缺少仔細的審察和普遍的函數庫支持。可是,scrypt在算法層面只要沒有破綻,它的安全性應該高於PBKDF2和bcrypt。

Java中使用scrypt

有一個Java實現的scrypt工具類庫(https://github.com/wg/scrypt )能夠直接使用。用法也比較簡單:

public static void main(String[] args) {

    String originalPassword = "漫話編程";

    String generatedSecuredPasswordHash = SCryptUtil.scrypt(originalPassword, 16, 16, 16);
    System.out.println(generatedSecuredPasswordHash);

    boolean matched = SCryptUtil.check("漫話編程", generatedSecuredPasswordHash);
    System.out.println(matched);

    matched = SCryptUtil.check("漫畫編程", generatedSecuredPasswordHash);
    System.out.println(matched);
}
複製代碼

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息