R. Martin R. Martin - 8 days ago 5
R Question

validating password in R with regex and POSIX character classes

I'm trying to validate a password in R using regex and POSIX character classes. I know a fair amount of regex but not the POSIX pieces. I've looked up the SO resources when asking a regex question, plus half a dozen SO questions and answers, such as this and that. The rules for the password are:


  • one uppercase letter

  • one lowercase letter

  • one or more special characters (ASCII punctuation)

  • between 8 and 32 characters

  • ASCII visible and space characters only



I've tried a number of code variations, as seen by the code that is commented out. I started building the regex at a lower level then worked my way up to the regex that should include all requirements.

ValidatePassword <- function(stringChar) {
# validPW <- "([[:lower:]]+[[:upper:]]+){8,32}"
# validPW <- "[[:lower:]]+[[:upper:]]+"
# validPW <- "^(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]])[[:print:]]{8,32}$"
# validPW <- "^(?:[[:lower:]])(?:[[:upper:]])(?:[[:punct:]])[[:print:]]{8,32}$"
# validPW <- "^(?:.*[[:lower:]])(?:.*[[:upper:]])(?:.*[[:punct:]])[[:print:]]{8,32}$"
# validPW <- "^([[:lower:]]+|[[:upper:]]+|[[:punct:]]+)[[:print:]]{8,32}$"
# validPW <- "^(?=.*[a-z])(?=.*[A-Z])(?=.*[[:punct:]])[[:print:]]{8,32}$"
# validPW <- "^([[:lower:][:upper:][:punct:]])[[:print:]]{8,32}"
validPW <- "^([[:lower:]]+|[[:upper:]]+|[[:punct:]]+)[[:print:]]{8,32}$"
return(length(grep(validPW, stringChar, value = TRUE)))
}
ifelse(ValidatePassword("#Password"), "valid", "not valid") # valid
ifelse(ValidatePassword("_PASSWORD"), "valid", "not valid") # not valid
ifelse(ValidatePassword("Password"), "valid", "not valid") # not valid
ifelse(ValidatePassword("password"), "valid", "not valid") # not valid
ifelse(ValidatePassword("passwor"), "valid", "not valid") # not valid
ifelse(ValidatePassword("pAsswords"), "valid", "not valid") # not valid
ifelse(ValidatePassword("Pa&sword"), "valid", "not valid") # valid
ifelse(ValidatePassword("Pa&s word"), "valid", "not valid") # valid


I realize that the code is not working properly even when the result says "valid". Can someone offer assistance? ty

Answer

You could use the following regular expression to validate:

is.validpw <- function(x) {
  re <- '(?x)                  # free-spacing mode
          ^                    # assert position = beginning of string
           (?=.*[[:upper:]])   # match one uppercase letter
           (?=.*[[:lower:]])   # match one lowercase letter
           (?=.*[[:punct:]])   # match one special character
           [ -~]{8,32}         # match printable ascii characters
          $                    # assert position = end of string'

  grepl(re, x, perl = TRUE)
}

is.validpw(c('#Password', '_PASSWORD', 'Password', 'password', 
             'passwor', 'pAsswords', 'Pa&sword', 'Pa&s word'))

## [1]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE