[譯] 基於機器學習的密碼強度檢測
原文:Machine Learning based Password Strength Classification
地址:http://web.archive.org/web/20170606022743/http://fsecurify.com/machine-learning-based-password-strength-checking/
近期,我想做一些機遇機器學習和網路安全的專案。這是另一個與資訊保安和機器學習有關的專案。
各公司的密碼強度檢測都不近相同。但所有的這些檢測都是基於規則的。一個密碼在Google這邊可能是強密碼但在Dropbox就變成了弱密碼。我在想我們能否讓機器學習演算法來決定一個密碼是弱密碼還是強密碼。於是,這個帖子誕生了。讓我們開始吧。
資料收集
此次分析所使用的密碼資料來自於000webhost洩漏,此資料可在網上下載。那麼我們是如何決定哪些密碼是高強度的哪些密碼是低強度的呢?Well,Georgia Tech university開發了一款名叫PARS的工具,這款工具集成了各大公司所使用的密碼強度檢測規則。這些檔案有兩行資料,密碼和強度。
我在此使用的密碼強度檢測演算法來自於Twitter,微軟和暴雪。這個演算法與其他檢測儀有什麼區別呢?首先,它是純粹基於機器學習而不是密碼規則的。其次,我只保留了那些三種檢測儀都認為強度是弱、中等、強的密碼。這意味著所有用來訓練的密碼的強度都確實是弱、中等、強的。
下面是一些用來訓練模型的密碼樣本:
0 for weak, 1 for medium and 2 for strong lamborghin1,1 AVYq1lDE4MgAZfNt,2 u6c8vhow,1 v1118714,1 universe2908,1 as326159,1 asv5o9yu,1 intel1,0 612035180tok,1 jytifok873,1 WUt9IZzE0OQ7PkNE,2 lsdlsd1,0
我原本有300萬條密碼資料,但是過濾出滿足三個密碼強度檢測儀後只剩下70萬條密碼資料了,我將這些資料分為了80%的訓練集和20%的測試集。其中過濾掉了許多資料是因為我只用了那些被三個分類演算法都認為是相同強度的密碼。
資料分析
我將使用Tf-idf分數而不是整條密碼,我將使用每個字元作為一個token。其他我沒用到的指標有密碼長度,特殊字元的數量,包含數字的數量等。這是一個自定義的令牌解析器(tokenizer)。
def getTokens(inputString): tokens = [] for i in inputString: tokens.append(i) return tokens
載入資料。
filepath = 'your_file_path_containing_passwords_and_labels' data = pd.read_csv(filepath,',',error_bad_lines=False) data = pd.DataFrame(data) passwords = np.array(data)
現在打亂資料集,然後獲取y和X向量。
random.shuffle(passwords) y = [d[1] for d in passwords] allpasswords= [d[0] for d in passwords]
現在在我們的密碼語料庫(corpus)上使用Tfidvectorizer分割資料。
vectorizer = TfidfVectorizer(tokenizer=getTokens) X = vectorizer.fit_transform(allpasswords) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
That's it. 現在我們需要做的就是應用機器學習演算法然後我門就擁有了一個基於機器學習的密碼強度檢測器。開工!由於我想讓演算法執行更快一些,在此我使用了多分類的邏輯迴歸演算法。
lgs = LogisticRegression(penalty='l2',multi_class='ovr') lgs.fit(X_train, y_train) print(lgs.score(X_test, y_test))
我們的準確率(accuracy)大概有81%,這可能是由於我們沒有使用大量的資料。這代表80%的情況下,我們演算法能夠將密碼正確分類(與三個商業的密碼檢測器分類結果相同)。讓我們來看看這個演算法是如何將我們的密碼分類的。
X_predict = ['faizanahmad','faizanahmad123','faizanahmad##','ajd1348#28t**','ffffffffff','kuiqwasdi','uiquiuiiuiuiuiuiuiuiuiuiui','mynameisfaizan','mynameis123faizan#','faizan','123456','abcdef'] X_predict = vectorizer.transform(X_predict) y_Predict = lgs.predict(X_predict) print y_Predict
來看看結果。
faizanahmad [medium] faizanahmad123 [medium] faizanahmad## [medium] ajd1348#28t** [strong] ffffffffff [easy] kuiqwasdi [medium] uiquiuiiuiuiuiuiuiuiuiuiui [easy] mynameis123faizan# [strong] faizan [easy] abcdef [easy]
看起來我們的演算法知道字母、數字和特殊符號的組合是一個好的密碼。很好,結果看起來很好,不是嗎?
有一些需要注意的地方,由於此模型是從已經存在的檢測演算法中的規則訓練的,但我組合了三種不同的檢測方法來使他更可靠(robust)。它不只是基於演算法模仿了一個規則。它綜合了廣泛使用的許多密碼強度檢查演算法。
這個專案是我在閒暇時間做的,它肯定是不完全的。這只是實現我心中的一個想法,然後分享與你們大家。我相信這個專案可以進一步擴充套件為更強大,更有意義的密碼檢測器/分類器。
程式碼和資料可以在此找到:
https://github.com/faizann24/Machine-Learning-based-Password-Strength-Classification