Quantcast
Channel: Simple command-line password generator - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 3

Simple command-line password generator

$
0
0

I'm very new to Haskell, I've read most of learnyouahaskell.com and played around with some simple things, but this is probably the most 'complicated' bit of Haskell I've written so far. I have an implementation in PHP that does basically the same thing, but it is much much faster.. I'm guessing my bottleneck here is that randomRIO takes a long time to return a value, is there any way to increase the speed, or get an array of values instead of grabbing them one at a time?

That aside, any other tips and/or suggestions about improving my implementation would be very helpful!

module Main whereimport System.Environmentimport System.Exitimport System.Random (randomRIO)import Control.Monad (replicateM)import qualified Data.Map as Mimport Text.Regex.Posixmain :: IO ()main = do    args <- getArgs    let helpOnly = "-h" `elem` args    if helpOnly        then putStrLn usage        else do        password <- generatePassword ("-w" `elem` args)        putStrLn password    exitSuccessusage :: Stringusage = unlines ["","Usage: [ -w, --with-symbols ] [ -h, --help ]","","By default, generates a 16 character password that does not include symbols.","","-w, --with-symbols  include symbols","-h, --help          print a brief help message"        ]symbols :: Stringsymbols = "!$%^&*()-_=+[{]};:@#~,<.>/?"randomReplace :: String -> String -> IO StringrandomReplace [] subject = return subjectrandomReplace (replacement:rs) subject = do    randomIndex <- randomRIO (0, length subject - 1) :: IO Int    let hash = zip [0 .. length subject - 1] subject    (randomReplace rs . map snd . M.toList .  M.insert randomIndex replacement . M.fromList) hashgeneratePassword :: Bool -> IO StringgeneratePassword withSymbols = do    let passwordLength = 500 -- obviously you wouldn't use 500 as a default here, but I'm just benchmarking    numDigits <- randomRIO (1, passwordLength) :: IO Int    digits <- replicateM numDigits (randomRIO (1, 9) :: IO Int)    numUppercase <- randomRIO (1, passwordLength) :: IO Int    uppercaseLetters <- replicateM numUppercase (randomRIO ('A', 'Z') :: IO Char)    p1 <- replicateM passwordLength (randomRIO ('a', 'z') :: IO Char)    p2 <- randomReplace (concatMap show digits) p1    p3 <- randomReplace uppercaseLetters p2    password <- if withSymbols        then do            numSymbols <- randomRIO (1, passwordLength) :: IO Int            symbolsToReplace <- replicateM numSymbols ((randomRIO (0, length symbols - 1) :: IO Int) >>= (\x -> return $ symbols !! x))            randomReplace symbolsToReplace p3        else return p3    if (password =~ "[a-z]" :: Bool) && (password =~ "[A-Z]" :: Bool) && (password =~ "[0-9]" :: Bool) -- we knows symbols are in there since it went last        then return password        else generatePassword withSymbols

Viewing all articles
Browse latest Browse all 3

Latest Images

Trending Articles





Latest Images