R Challenge #5: Passwords
Treat your password like your toothbrush. Don't let anybody else use it, and get a new one every six months.
Clifford Stoll
R Challenge #5 : Diagnose a list of passwords
LinkedIn Learning just released a new course;?R Data Science Code Challenges. It's a collection of fifteen amusing problems to be solved with knowledge of the R language.
In this challenge we use R to check the validity of a password. Valid passwords are defined as:
You are given a file with first name and password - these are the passwords to check. It looks like this...
Check each password and if it fails one of the tests, generate a report that describes which condition it doesn't satisfy. There are only 9,000 passwords to check - so let's get cracking!
video of challenge
Here's My Solution
You'll note I've leaned heavily on grep patterns. No surprise!
领英推荐
testThesePasswords <- AcmeData_Demographic$surveyID
diagnosePassword <- function(aPassword) {
? return(c(length = nchar(aPassword) > 10,
? ? ? ? ? lowercase = grepl(pattern = "[[:lower:]]", x = aPassword ),
? ? ? ? ??uppercase = grepl(pattern = "[[:upper:]]", x = aPassword ),
? ? ? ? ?number = grepl(pattern = "[[:digit:]]", x = aPassword ),
? ? ? ?? ?punctuation = grepl(pattern = "[[:punct:]]", x = aPassword )?
? ? ? ? ? ?) )
?
}
for (aPassword in testThesePasswords) {
? passwordTest <- diagnosePassword(aPassword)
? if (! all(passwordTest)) {
? ? if (exists("passwordTestResults")) {
? ? ? newRow <- c(aPassword,passwordTest)
? ? ? passwordTestResults <- rbind(passwordTestResults,newRow)
? ? } else {
? ? ? passwordTestResults <- data.frame(password = aPassword,
? ? ? ? ? ? ? ? ? ? ? ? ?? length = passwordTest["length"],
? ? ? ? ? ? ?? ? ? ? ? ? ? lowercase = passwordTest["lowercase"],
? ? ? ? ? ? ? ? ? ? ? ?? ? uppercase = passwordTest["uppercase"],
? ? ? ? ? ? ? ? ? ?? ? ? ? number = passwordTest["number"],
? ? ? ? ? ? ? ? ? ? ? ? ? ? punctuation = passwordTest["punctuation"],
? ? ? ? ? ? ? ? ? ? ? ? ? ? row.names = NULL)
? ? }
? }
}
And...here's what my report looks like...
The Hidden Story
There is healthy debate on what makes up a safe password. My criteria is useful - but certainly not bombproof.
Looking back, it would have also been interesting to compare each password against the list of most common passwords. There are several lists, here's the SecLists version with 10,000 passwords. Most common are 123456, password, 12345678, qwerty, 123456789, 12345, 1234, 111111, 1234567, and dragon. It would be a simple use of %in% - perhaps you'll be the first to post that line of code in the comments. Better yet - issue a pull to my GitHub with the solution!
Take a look at the code I used to generate the list...
# Passwords --------------
#install.packages("fun")
library(fun)
Top10000Passwords <- read.table(file = "https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10-million-password-list-top-10000.txt")
Top10000Passwords <- Top10000Passwords$V1
badWords <- read.csv(file = "https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en")
badWords <- badWords$X2g1c
Top10000Passwords <- Top10000Passwords[! ?Top10000Passwords %in% badWords]
surveyID <- NULL
for (passwordIndex in 1:lengthOfFirstNames) {
? if (rnorm(1) > 2) {
? ? uniqueTTP <- sample(Top10000Passwords,size = 1)
? ? while(uniqueTTP %in% surveyID) { ? ?
? ? ? uniqueTTP <- sample(Top10000Passwords,size = 1)
? ? }
? ? surveyID[passwordIndex] <- uniqueTTP
? } else { surveyID[passwordIndex] <- random_password(15)}
}
You'll see I use fun::random_password to create the passwords and once in a while I add one of the most-common 10,000. For the sake of building a family-friendly list of passwords, I also filter the 10,000 through a list of obscene words.
How about you??
In this and future articles, I'll share some backstory behind each R challenge in this course. My peers have supplied other code challenges you might find interesting:?Javascript?...?Python?...?Java?...?Github?...?HTML?...?SQL?...?SQL for Data Science?...?PHP
Do you have some opinions on this challenge? Please share them in the comments below.
mnr