From f80b4347a6d3347b83ba57f241c0fa269a8ae316 Mon Sep 17 00:00:00 2001 From: Romain Edelmann Date: Sun, 11 Aug 2013 20:18:11 +0200 Subject: [PATCH] Added possibility to enter an extra code (typically a long code, written down on a card). --- scat.cabal | 2 +- src/Scat.hs | 36 +++++++++++++++++++++++++----------- src/Scat/Options.hs | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/scat.cabal b/scat.cabal index d22beb2..be6dc0b 100644 --- a/scat.cabal +++ b/scat.cabal @@ -10,7 +10,7 @@ name: scat -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 0.2.0.0 +version: 0.2.1.0 -- A short (one-line) description of the package. synopsis: Generates unique passwords for various websites from a single password. diff --git a/src/Scat.hs b/src/Scat.hs index 9bad0d6..557c17f 100644 --- a/src/Scat.hs +++ b/src/Scat.hs @@ -3,6 +3,7 @@ -- | Password scatterer. module Main (main) where +import Data.Monoid import Data.ByteString (ByteString) import Data.ByteString (unpack) import qualified Data.ByteString.Char8 as C @@ -17,9 +18,9 @@ import Scat.Builder import Scat.Options -- | Generates the seed integer given a key and a password. -scatter :: ByteString -> ByteString -> Integer -scatter k pw = foldr (\ c s -> fromIntegral c + 256 * s) 0 $ - unpack $ unHash $ scrypt params (Salt k) (Pass pw) +scatter :: ByteString -> ByteString -> ByteString -> Integer +scatter k pw c = foldr (\ n s -> fromIntegral n + 256 * s) 0 $ + unpack $ unHash $ scrypt params (Salt k) (Pass $ pw <> c) where Just params = scryptParams 14 8 50 @@ -41,8 +42,9 @@ scat = do k <- getKey s <- getSchema pw <- getPassword + c <- getCode printVerbose "Generated password:\n" - liftIO $ putStrLn $ evalBuilder s $ scatter k pw + liftIO $ putStrLn $ evalBuilder s $ scatter k pw c -- | Prints, if the verbosity level allows it. printVerbose :: String -> Scat () @@ -67,11 +69,11 @@ getPassword = do -- Retrieve the password from the arguments. Just st -> return $ C.pack st where - getPass = askPassword "Password: " + getPass = askPassword False "Password: " getPassConfirm = do - a <- askPassword "Password: " - b <- askPassword "Confirm: " + a <- askPassword False "Password: " + b <- askPassword False "Confirm: " if a == b then return a else do @@ -79,21 +81,33 @@ getPassword = do getPassConfirm -- | Ask a password on the command line, with the specified prompt. -askPassword :: String -> Scat C.ByteString -askPassword str = do +askPassword :: Bool -> String -> Scat ByteString +askPassword echo str = do printVerbose str old <- liftIO $ hGetEcho stdin pw <- liftIO $ bracket_ - (hSetEcho stdin False) + (hSetEcho stdin echo) (hSetEcho stdin old) C.getLine - printVerbose "\n" + unless echo $ printVerbose "\n" return pw -- | Gets the key. getKey :: Scat ByteString getKey = fmap (C.pack . key) ask +-- | Gets the code. +getCode :: Scat ByteString +getCode = do + uc <- fmap useCode ask + if uc + then do + mc <- fmap code ask + case mc of + Just st -> return $ C.pack st + Nothing -> askPassword True "Code: " + else return "" + -- | Gets the schema to generate the new password. getSchema :: Scat Schema getSchema = do diff --git a/src/Scat/Options.hs b/src/Scat/Options.hs index 881a867..a296803 100644 --- a/src/Scat/Options.hs +++ b/src/Scat/Options.hs @@ -8,6 +8,8 @@ module Scat.Options -- * Accessors , password , key + , useCode + , code , schema , verbose , confirm @@ -17,6 +19,7 @@ module Scat.Options ) where import Data.Monoid +import Data.Maybe (isJust) import Options.Applicative -- | All program options. @@ -25,6 +28,10 @@ data Options = Options -- ^ Password, optionally provided. , key :: String -- ^ Key or category for the password. + , useCode_ :: Bool + -- ^ Indicates if extra code should be used. + , code :: Maybe String + -- ^ Extra code. Activates code usage. , schema :: String -- ^ Name of the schema to use. , verbose_ :: Bool @@ -33,6 +40,10 @@ data Options = Options -- ^ Indicates if the password must be confirmed. Activates verbosity. } +-- | Indicates if extra code should be used. +useCode :: Options -> Bool +useCode opts = useCode_ opts || isJust (code opts) + {- | Verbosity. If false, do not print anything but the generated password. True when @--verbose@ or @--confirmation@ are specified. -} verbose :: Options -> Bool @@ -60,6 +71,14 @@ options = Options <> long "key" <> help "Key associated (website, email address, ...) (mandatory)" <> metavar "KEY") + <*> switch + (short 'x' + <> long "extra" + <> help "Indicates extra code should be used.") + <*> optional + (strOption (long "code" + <> help "Extra code." + <> metavar "CODE")) <*> strOption (short 's' <> long "schema"