mirror of
https://github.com/redelmann/scat
synced 2025-04-20 12:38:38 +02:00
Modifies options so that the use of code is strongly encouraged.
This commit is contained in:
parent
83288f00d7
commit
b14cf29657
@ -10,7 +10,7 @@ name: scat
|
||||
-- PVP summary: +-+------- breaking API changes
|
||||
-- | | +----- non-breaking API additions
|
||||
-- | | | +--- code changes with no API change
|
||||
version: 0.2.1.0
|
||||
version: 1.0.0.0
|
||||
|
||||
-- A short (one-line) description of the package.
|
||||
synopsis: Generates unique passwords for various websites from a single password.
|
||||
@ -63,5 +63,5 @@ executable scat
|
||||
other-modules: Scat.Builder, Scat.Schemas, Scat.Options, Scat.Utils.Permutation, Paths_scat
|
||||
|
||||
-- Other library packages from which modules are imported.
|
||||
build-depends: base ==4.5.*, scrypt ==0.3.*, bytestring ==0.9.*, optparse-applicative ==0.5.*, mtl ==2.1.*, vector ==0.10.*
|
||||
build-depends: base ==4.5.*, scrypt ==0.3.*, bytestring ==0.9.*, optparse-applicative ==0.5.*, mtl ==2.1.*, vector ==0.10.*, ansi-terminal ==0.6.*
|
||||
|
63
src/Scat.hs
63
src/Scat.hs
@ -9,6 +9,7 @@ import Data.ByteString (unpack)
|
||||
import qualified Data.ByteString.Char8 as C
|
||||
import System.IO
|
||||
import System.Exit
|
||||
import System.Console.ANSI
|
||||
import Control.Exception
|
||||
import Control.Monad.Reader
|
||||
import Crypto.Scrypt
|
||||
@ -17,19 +18,34 @@ import Scat.Schemas
|
||||
import Scat.Builder
|
||||
import Scat.Options
|
||||
|
||||
-- | Generates the seed integer given a key and a password.
|
||||
-- | Generates the seed integer given a service, a password and a code.
|
||||
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
|
||||
unpack $ unHash $ scrypt params (Salt k) (Pass $ pw <> c)
|
||||
where
|
||||
Just params = scryptParams 14 8 50
|
||||
|
||||
-- | Main type of the program.
|
||||
type Scat a = ReaderT Options IO a
|
||||
|
||||
-- | Input visibility.
|
||||
data Visibility = Shown | Hidden | Erased
|
||||
|
||||
-- | Should the input be echoed?
|
||||
shouldShow :: Visibility -> Bool
|
||||
shouldShow Shown = True
|
||||
shouldShow Hidden = False
|
||||
shouldShow Erased = True
|
||||
|
||||
-- | Should the input be erased afterwards?
|
||||
shouldErase :: Visibility -> Bool
|
||||
shouldErase Shown = False
|
||||
shouldErase Hidden = False
|
||||
shouldErase Erased = True
|
||||
|
||||
{- | Generates a password, given a input password,
|
||||
a key (category, website, etc.),
|
||||
and a password `Schema`.
|
||||
a service name (category, website, etc.),
|
||||
a code, and a password `Schema`.
|
||||
|
||||
The parameters are specified as command line arguments.
|
||||
The password can be read from @stdin@ if not already provided. -}
|
||||
@ -39,7 +55,7 @@ main = getOptions >>= runReaderT scat
|
||||
-- | Main program.
|
||||
scat :: Scat ()
|
||||
scat = do
|
||||
k <- getKey
|
||||
k <- getService
|
||||
s <- getSchema
|
||||
pw <- getPassword
|
||||
c <- getCode
|
||||
@ -69,32 +85,41 @@ getPassword = do
|
||||
-- Retrieve the password from the arguments.
|
||||
Just st -> return $ C.pack st
|
||||
where
|
||||
getPass = askPassword False "Password: "
|
||||
getPass = prompt Hidden "Password: "
|
||||
|
||||
getPassConfirm = do
|
||||
a <- askPassword False "Password: "
|
||||
b <- askPassword False "Confirm: "
|
||||
a <- prompt Hidden "Password: "
|
||||
b <- prompt Hidden "Confirm: "
|
||||
if a == b
|
||||
then return a
|
||||
else do
|
||||
printVerbose "Passwords do not match, please retry.\n"
|
||||
getPassConfirm
|
||||
|
||||
-- | Ask a password on the command line, with the specified prompt.
|
||||
askPassword :: Bool -> String -> Scat ByteString
|
||||
askPassword echo str = do
|
||||
-- | Ask a for input on the command line, with the specified prompt.
|
||||
prompt :: Visibility -> String -> Scat ByteString
|
||||
prompt vis str = do
|
||||
printVerbose str
|
||||
old <- liftIO $ hGetEcho stdin
|
||||
pw <- liftIO $ bracket_
|
||||
(hSetEcho stdin echo)
|
||||
(hSetEcho stdin $ shouldShow vis)
|
||||
(hSetEcho stdin old)
|
||||
C.getLine
|
||||
unless echo $ printVerbose "\n"
|
||||
when (shouldErase vis) $ liftIO $ do
|
||||
cursorUpLine 1
|
||||
cursorForward $ length str
|
||||
clearFromCursorToScreenEnd
|
||||
cursorDownLine 1
|
||||
unless (shouldShow vis) $ printVerbose "\n"
|
||||
return pw
|
||||
|
||||
-- | Gets the key.
|
||||
getKey :: Scat ByteString
|
||||
getKey = fmap (C.pack . key) ask
|
||||
-- | Gets the service.
|
||||
getService :: Scat ByteString
|
||||
getService = do
|
||||
mk <- fmap service ask
|
||||
case mk of
|
||||
Just k -> return $ C.pack k
|
||||
Nothing -> prompt Shown "Service: "
|
||||
|
||||
-- | Gets the code.
|
||||
getCode :: Scat ByteString
|
||||
@ -105,7 +130,7 @@ getCode = do
|
||||
mc <- fmap code ask
|
||||
case mc of
|
||||
Just st -> return $ C.pack st
|
||||
Nothing -> askPassword True "Code: "
|
||||
Nothing -> prompt Erased "Code: "
|
||||
else return ""
|
||||
|
||||
-- | Gets the schema to generate the new password.
|
||||
|
@ -7,7 +7,7 @@ module Scat.Options
|
||||
|
||||
-- * Accessors
|
||||
, password
|
||||
, key
|
||||
, service
|
||||
, useCode
|
||||
, code
|
||||
, schema
|
||||
@ -19,43 +19,33 @@ module Scat.Options
|
||||
) where
|
||||
|
||||
import Data.Monoid
|
||||
import Data.Maybe (isJust)
|
||||
import Options.Applicative
|
||||
|
||||
-- | All program options.
|
||||
data Options = Options
|
||||
{ password :: Maybe String
|
||||
-- ^ Password, optionally provided.
|
||||
, key :: String
|
||||
-- ^ Key or category for the password.
|
||||
, useCode_ :: Bool
|
||||
, service :: Maybe String
|
||||
-- ^ Service for which to generate the password.
|
||||
, useCode :: Bool
|
||||
-- ^ Indicates if extra code should be used.
|
||||
, code :: Maybe String
|
||||
-- ^ Extra code. Activates code usage.
|
||||
-- ^ Extra code.
|
||||
, schema :: String
|
||||
-- ^ Name of the schema to use.
|
||||
, verbose_ :: Bool
|
||||
, verbose :: Bool
|
||||
-- ^ Verbosity. If false, do not print anything but the generated password.
|
||||
, confirm :: Bool
|
||||
-- ^ Indicates if the password must be confirmed. Activates verbosity.
|
||||
-- ^ Indicates if the password must be confirmed.
|
||||
}
|
||||
|
||||
-- | 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
|
||||
verbose opts = verbose_ opts || confirm opts
|
||||
|
||||
-- | Parses the arguments from the command line.
|
||||
getOptions :: IO Options
|
||||
getOptions = execParser opts
|
||||
where
|
||||
opts = info (helper <*> options)
|
||||
(fullDesc
|
||||
<> progDesc "Safely generate passwords derived from a unique password."
|
||||
<> progDesc "Safely generate passwords derived from a unique password and code."
|
||||
<> header "scat - a password scatterer")
|
||||
|
||||
-- | Option parser.
|
||||
@ -66,18 +56,18 @@ options = Options
|
||||
<> long "password"
|
||||
<> help "The password"
|
||||
<> metavar "PASSWORD"))
|
||||
<*> strOption
|
||||
(short 'k'
|
||||
<> 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
|
||||
(short 'S'
|
||||
<> long "service"
|
||||
<> help "Service associated (website, email address, ...)"
|
||||
<> metavar "SERVICE"))
|
||||
<*> flag True False
|
||||
(long "nocode"
|
||||
<> help "Indicates that extra code should be not be used")
|
||||
<*> optional
|
||||
(strOption (long "code"
|
||||
<> help "Extra code."
|
||||
(strOption (short 'x'
|
||||
<> long "code"
|
||||
<> help "The extra code to use"
|
||||
<> metavar "CODE"))
|
||||
<*> strOption
|
||||
(short 's'
|
||||
@ -86,10 +76,9 @@ options = Options
|
||||
<> metavar "SCHEMA"
|
||||
<> value "safe"
|
||||
<> showDefault)
|
||||
<*> switch
|
||||
(short 'v'
|
||||
<> long "verbose"
|
||||
<> help "Prints instructions and information")
|
||||
<*> flag True False
|
||||
(long "silent"
|
||||
<> help "Do not print anything but the generated password")
|
||||
<*> switch
|
||||
(short 'c'
|
||||
<> long "confirmation"
|
||||
|
Loading…
Reference in New Issue
Block a user