1
0
mirror of https://github.com/redelmann/scat synced 2025-01-10 06:34:20 +01:00

Added possibility to enter an extra code (typically a long code, written down on a card).

This commit is contained in:
Romain Edelmann 2013-08-11 20:18:11 +02:00
parent 248c2ca707
commit f80b4347a6
3 changed files with 45 additions and 12 deletions

View File

@ -10,7 +10,7 @@ name: scat
-- PVP summary: +-+------- breaking API changes -- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions -- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change -- | | | +--- code changes with no API change
version: 0.2.0.0 version: 0.2.1.0
-- A short (one-line) description of the package. -- A short (one-line) description of the package.
synopsis: Generates unique passwords for various websites from a single password. synopsis: Generates unique passwords for various websites from a single password.

View File

@ -3,6 +3,7 @@
-- | Password scatterer. -- | Password scatterer.
module Main (main) where module Main (main) where
import Data.Monoid
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.ByteString (unpack) import Data.ByteString (unpack)
import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Char8 as C
@ -17,9 +18,9 @@ import Scat.Builder
import Scat.Options import Scat.Options
-- | Generates the seed integer given a key and a password. -- | Generates the seed integer given a key and a password.
scatter :: ByteString -> ByteString -> Integer scatter :: ByteString -> ByteString -> ByteString -> Integer
scatter k pw = foldr (\ c s -> fromIntegral c + 256 * s) 0 $ scatter k pw c = foldr (\ n s -> fromIntegral n + 256 * s) 0 $
unpack $ unHash $ scrypt params (Salt k) (Pass pw) unpack $ unHash $ scrypt params (Salt k) (Pass $ pw <> c)
where where
Just params = scryptParams 14 8 50 Just params = scryptParams 14 8 50
@ -41,8 +42,9 @@ scat = do
k <- getKey k <- getKey
s <- getSchema s <- getSchema
pw <- getPassword pw <- getPassword
c <- getCode
printVerbose "Generated password:\n" 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. -- | Prints, if the verbosity level allows it.
printVerbose :: String -> Scat () printVerbose :: String -> Scat ()
@ -67,11 +69,11 @@ getPassword = do
-- Retrieve the password from the arguments. -- Retrieve the password from the arguments.
Just st -> return $ C.pack st Just st -> return $ C.pack st
where where
getPass = askPassword "Password: " getPass = askPassword False "Password: "
getPassConfirm = do getPassConfirm = do
a <- askPassword "Password: " a <- askPassword False "Password: "
b <- askPassword "Confirm: " b <- askPassword False "Confirm: "
if a == b if a == b
then return a then return a
else do else do
@ -79,21 +81,33 @@ getPassword = do
getPassConfirm getPassConfirm
-- | Ask a password on the command line, with the specified prompt. -- | Ask a password on the command line, with the specified prompt.
askPassword :: String -> Scat C.ByteString askPassword :: Bool -> String -> Scat ByteString
askPassword str = do askPassword echo str = do
printVerbose str printVerbose str
old <- liftIO $ hGetEcho stdin old <- liftIO $ hGetEcho stdin
pw <- liftIO $ bracket_ pw <- liftIO $ bracket_
(hSetEcho stdin False) (hSetEcho stdin echo)
(hSetEcho stdin old) (hSetEcho stdin old)
C.getLine C.getLine
printVerbose "\n" unless echo $ printVerbose "\n"
return pw return pw
-- | Gets the key. -- | Gets the key.
getKey :: Scat ByteString getKey :: Scat ByteString
getKey = fmap (C.pack . key) ask 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. -- | Gets the schema to generate the new password.
getSchema :: Scat Schema getSchema :: Scat Schema
getSchema = do getSchema = do

View File

@ -8,6 +8,8 @@ module Scat.Options
-- * Accessors -- * Accessors
, password , password
, key , key
, useCode
, code
, schema , schema
, verbose , verbose
, confirm , confirm
@ -17,6 +19,7 @@ module Scat.Options
) where ) where
import Data.Monoid import Data.Monoid
import Data.Maybe (isJust)
import Options.Applicative import Options.Applicative
-- | All program options. -- | All program options.
@ -25,6 +28,10 @@ data Options = Options
-- ^ Password, optionally provided. -- ^ Password, optionally provided.
, key :: String , key :: String
-- ^ Key or category for the password. -- ^ 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 , schema :: String
-- ^ Name of the schema to use. -- ^ Name of the schema to use.
, verbose_ :: Bool , verbose_ :: Bool
@ -33,6 +40,10 @@ data Options = Options
-- ^ Indicates if the password must be confirmed. Activates verbosity. -- ^ 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. {- | Verbosity. If false, do not print anything but the generated password.
True when @--verbose@ or @--confirmation@ are specified. -} True when @--verbose@ or @--confirmation@ are specified. -}
verbose :: Options -> Bool verbose :: Options -> Bool
@ -60,6 +71,14 @@ options = Options
<> long "key" <> long "key"
<> help "Key associated (website, email address, ...) (mandatory)" <> help "Key associated (website, email address, ...) (mandatory)"
<> metavar "KEY") <> metavar "KEY")
<*> switch
(short 'x'
<> long "extra"
<> help "Indicates extra code should be used.")
<*> optional
(strOption (long "code"
<> help "Extra code."
<> metavar "CODE"))
<*> strOption <*> strOption
(short 's' (short 's'
<> long "schema" <> long "schema"