wordpass-1.0.0.0: WordPass.hs
{-# LANGUAGE TemplateHaskell, NoMonomorphismRestriction #-}
-- | Main module generating passwords.
module Main where
import qualified Data.Text.IO as Text
import qualified Data.Set as Set
import Data.Random.Sample
import Data.Random.RVar.Enum()
import Data.Random.Source.DevRandom
import Data.Random.Source.IO()
import qualified Data.Vector as V
import Control.Applicative
import Control.Monad (replicateM_)
import HFlags
import Text.WordPass
-- * Command-line flags
-- | Number of words per password
defineFlag "w:words" (4 :: Int) "Number of words for each password."
-- | Number of passwords
defineFlag "p:passwords" (10 :: Int) "Number of passwords to generate."
-- | Default word list directory.
defineFlag "d:directory" ("/usr/share/dict" :: FilePath) "Default directory to search for dictionaries\n (works only if --wordlist options is NOT USED.)"
-- | Pick specific wordlist.
defineFlag "l:wordlist" ("" :: FilePath) "Select particular dictionary (filepath)."
-- | Pick specific wordlist.
defineFlag "t:pseudorandom" (False :: Bool) "Generate passwords using StdRandom generator, instead of DevRandom. (Faster, but less safe. Good for testing."
-- | Fake flag to avoid GHC losing the last instance declaration
defineFlag "fakeflag" (False :: Bool) "This flag does nothing and is never used"
-- | Read wordlist given by explict filepath, or search for all wordlists in a given directory.
selectWordList :: FilePath -> FilePath -> IO WordSet
selectWordList "" dir = readDictDir dir
selectWordList filename _ = readDict filename
main :: IO ()
main = do _args <- $initHFlags "WordPass - dictionary-based password generator"
dictWords <- (V.fromList . Set.toList) <$> selectWordList flags_wordlist flags_directory
putStrLn $ "Read " ++ show (V.length dictWords) ++ " words from dictionaries."
putStr "Estimated password strength (bits): "
print $ randomPasswordStrength dictWords flags_words
replicateM_ flags_passwords $ do
let rand = randomPassword dictWords flags_words
rv <- if flags_pseudorandom
then sample rand
else sampleFrom DevRandom rand
Text.putStrLn rv