در قسمت اول این پست، یک فایل متنی حاوی دو میلیون پسورد را در R وارد کردیم و نشان دادیک که داخل آن چه خبر است، پسوردها عموما از چه چیزهایی تشکیل شدهاند و یکی دو تا نمودار دربارهی ترکیب پسوردها رسم کردیم، حالا نوبت این رسیده که قدرت این پسوردها را بسنجیم. تحلیل اصلی که روی گیتهاب و به زبان پایتون انجام شده بود، روش سنجش قدرت پسورد را از اینجا گرفته و کمی تغییر داده بود تا به قوانین زیر برسد:
اضافات:
- تعداد کاراکترها: طول * ۴
- تعداد حروف بزرگ: طول * ۳
- تعداد حروف کوچک: طول * ۳
- تعداد ارقام: طول * ۲.۵
- کاراکترهای ویژه: طول * ۴
- ترکیبی از دو مورد بالا: طول
- ترکیبی از سه مورد بالا: طول * ۱.۵
- ترکیبی از هر چهار مورد: طول * ۲
کسورات:
- فقط حروف: –طول
- فقط اعداد: –طول
- فقط کاراکترهای ویژه: –طول
- کاراکتر تکراری: –طول
ما هم همین داستان را در قالب یک تابع در R پیاده میکنیم:
passstrength <- function(x) { xsplit <- strsplit(x , split = "")[[1]] #طول پسورد s <- nchar(x) * 4 #محاسبه تعداد کاراکترهای دارای تکرار s <- s - (nchar(x) - length(unique(xsplit))) #محاسبه امتیاز نوع کاراکترها type <- function(x){ if(grepl("[[:lower:]]",x)== TRUE) {type = "small" } if(grepl("[[:upper:]]",x)== TRUE) {type = "capital" } if(grepl("[[:digit:]]",x)== TRUE) {type = "digit" } if(grepl("[[:punct:]]",x)== TRUE) {type = "symbol" } type } f <- as.data.frame(cbind(xsplit, type= sapply(xsplit,type))) s <- s + (sum(f$type =="small") * 3) s <- s + (sum(f$type =="capital") * 3) s <- s + (sum(f$type =="digit") * 2.5) s <- s + (sum(f$type =="symbol") * 4) #محاسبه تعداد گروههای کاراکترها c = 0 d = 0 if(grepl("[[:alpha:]]",x)== TRUE) {c = c + 1 ; d = d+1} if(grepl("[[:upper:]]",x)== TRUE) {c = c + 1 } if(grepl("[[:digit:]]",x)== TRUE) {c = c + 1 ; d = d+1} if(grepl("[[:punct:]]",x)== TRUE) {c = c + 1 ; d = d+1} if(c == 2){s <- s + nchar(x) } if(c == 3){s <- s + (nchar(x) * 1.5) } if(c == 4){s <- s + (nchar(x) * 2) } if(d == 1){s <- s - nchar(x) } s }
الان یک تابع داریم که یک پسورد را از ما میگیرد، کمی محاسبات روی تعداد و نوع کاراکترهای آن انجام میدهد و یک عدد به عنوان قدرت پسورد تحویل میدهد. قرار است این تابع را روی ۲ میلیون عضو یک بردار اجرا کنیم، اولین چیزی که وارد ذهن میشود استفاده از حلقه for است اما جالب است بدانید به دلیل پشتیبانی از بردار، ماتریس و ساختارهای داده در R، در بسیاری از مواقع نیازی به استفاده از حلقه و ساختارهای کنترلی نداریم و به جای آن میتوانیم از خانوادهی توابع apply استفاده کنیم.این توایع، یک تابع(که میتواند تابع نوشته شده توسط خودتان یا یکی از توابع R) را از شما میگیرد و آن را روی جهتی که شما تعیین میکنید( مثلا در طول بردار، در طول ستونها یا ردیفهای ماتریس) اجرا میکند. در اینجا از تابع sapply از این خانواده استفاده میکنیم و آن را به جدولی که در پست قبلی ساخته بودیم متصل میکنیم:
m <- sapply(passwords, passstrength) pass <- cbind(pass , score = m)
این دستور خیلی طول میکشد، دلیلش هم این است که R به طور پیشفرض، از پردازشهای موازی و چندهستهای استفاده نمیکند. برای قدم آخر این تحلیل، پسوردها را در پنج دسته شامل خیلی ضعیف، ضعیف، متوسط، قوی و خیلی قوی دخیره میکنیم:
classs <- function(x) { class <- NULL if(x < 40 ){ class ="very weak" } if(x >= 40 && x < 60) { class = "weak"} if(x >= 60 && x < 80) { class = "good"} if(x >= 80 && x < 90) { class = "strong"} if(x >= 90 ) { class = "very strong"} class } pass <- cbind( pass , class = n)
و با رسم یک نمودار میلهای فراوانی به کارمان پایان میدهیم:
library(ggplot2) ggplot(data=pass ,aes(x=class)) + geom_bar(fill="darkred", colour="black") + geom_text(stat='count',aes(label=..count..),vjust=-1)
نتیجهای که از این پست و قسمت قبلی آن میتوان گرفت این است که بیشتر پسوردها، طبق قوانین و روابطی که برای محاسبهی قدرت پسورد استفاده میشود ( و ما از نسخه بسیار سادهی آنها در این تحیلی استفاده نمودیم) ضعیف محسوب میشوند. البته این روابط در نهایت فقط یه عدد تحویل میدهند و این کاربر است که با انتخاب هوشمندانه، دقت به موارد امنیتی و تعویض دورهای قدرت پسورد خود را تعیین میکنند.
پینوشت: همانطور که در اول پست قبلی هم دکر شد، این تحلیل متعلق به بنده نیست و از یک تحلیل به زبان پایتون روی گیتهاب نوشته شده است. هدف این دو پست را میةوان نشان دادن این موضوع که R و پایتون میتوانند در مواردی مشابه استفاده شوند دانست.