packages feed

wordpass (empty) → 0.1.0.0

raw patch · 5 files changed

+165/−0 lines, 5 filesdep +basedep +containersdep +directorysetup-changed

Dependencies added: base, containers, directory, random-fu, random-source, text, vector

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Michal J. Gajda++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Michal J. Gajda nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,7 @@+WordPass+========++Dictionary-based password generator.++Uses dictionaries from /usr/share/dict by default.+You might want to look and change the code, since it is not intended as CLI yet :-).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ WordPass.hs view
@@ -0,0 +1,101 @@+-- | Main module generating passwords.+module Main where++import           System.Directory(getDirectoryContents)+import qualified Data.Text    as Text+import qualified Data.Text.IO as Text+import           Data.Text(Text)+import qualified Data.Set     as Set+import           Data.Char           (isAlpha, isPunctuation, isSymbol)+import           Data.Random.RVar+import           Data.Random.Sample+import           Data.Random.RVar.Enum+import           Data.Random.Distribution+import           Data.Random.Distribution.Uniform+import           Data.Random.Source.IO+import qualified Data.Vector  as V+import           Control.Applicative+import           Control.Monad       (replicateM, foldM)++-- | Reads a dict format to get a list of unique words without any special+--   chars.+readDict ::  FilePath -> IO (V.Vector Text)+readDict filename = do+    input <- Text.readFile filename+    return $! V.fromList . Set.toList . Set.fromList . map stripTails . Text.lines $! input+  where+    stripTails = head . Text.split (not . isAlpha)++-- | Find all plausible dictionaries in a given directory+dictFiles dir = postprocess `fmap`+                  getDirectoryContents dir+  where+    postprocess = map ((dir ++ "/") ++) . filter (not . (=='.') . head)++-- | Default directory where to look for the word lists.+defaultDictDir :: FilePath+defaultDictDir = "/usr/share/dict"++-- | Read a set of dictionaries and put the together.+readDicts filenames = (V.fromList . Set.toList) `fmap` foldM action Set.empty filenames+  where+    action currentSet filename = do newSet <- readDict filename+                                    return $! Set.fromList (V.toList newSet) `Set.union` currentSet++-- | Read all dictionaries from a given directory.+readDictDir dirname = dictFiles dirname >>= readDicts++-- | Filename for default dictionary (should be command line argument or default glob.)+defaultDictionary ::  FilePath+defaultDictionary = "/usr/share/dict/british-english"++-- | Take a random element of a vector.+randomElement :: V.Vector a -> RVar a+randomElement words = (words V.!) <$> uniform 0 (V.length words - 1)++-- | Pick a random password, given a words list, and a number of words it will contain.+randomPassword :: V.Vector Text -> Int -> RVar Text+randomPassword words numWords = do ws   <- replicateM numWords $ randomElement words+                                   seps <- replicateM numWords randomSeparator+                                   return $ Text.concat $ zipWith Text.append ws seps++-- | Estimate strength of random password with given inputs.+randomPasswordStrength words numWords = fromIntegral numWords * logBase 2 wordStrength+  where+    wordStrength = fromIntegral $ V.length words * (32 + 100)++-- * Random separators+-- | Randomly pick a word separator as a two-digit number, or a symbol+--   character.+randomSeparator ::  RVar Text+randomSeparator = do b <- uniform False True+                     if b then symbolSeparator+                          else numericSeparator++-- | Two-digit number as a separator 10^2 = 6.6 bits of entropy.+numericSeparator ::  RVar Text+numericSeparator = Text.pack <$> show <$> uniform 0 (99 :: Int)++-- | Conjunction of two unary predicates+(|||) ::  (t -> Bool) -> (t -> Bool) -> t -> Bool+(|||) f g x = f x || g x++-- | List of symbol and punctuation characters in ASCII+--   Should be 5 bits of entropy+symbolChars ::  V.Vector Char+symbolChars = V.fromList $ filter (isSymbol ||| isPunctuation) $ map toEnum [0..127]++-- | Text with random symbol character, 5 bits of entropy+symbolSeparator ::  RVar Text+symbolSeparator = Text.singleton <$> randomElement symbolChars++main = do dictWords <- readDictDir defaultDictDir+          --print $ V.length dictWords+          putStr "Estimated password strength (bits): "+          print $ randomPasswordStrength dictWords numWs+          replicateM 5 $ do +            rv <- sample $ randomPassword dictWords numWs+            Text.putStrLn rv+  where+    numWs = 5+  
+ wordpass.cabal view
@@ -0,0 +1,25 @@+-- Initial wordpass.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                wordpass+version:             0.1.0.0+synopsis:            Dictionary-based password generator+-- description:         +homepage:            https://github.com/mjgajda/wordpass+license:             BSD3+license-file:        LICENSE+author:              Michal J. Gajda+maintainer:          mjgajda@gmail.com+-- copyright:           +category:            System+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10++executable wordpass+  main-is:             WordPass.hs+  -- other-modules:    Data.Random.RVar.Enum   +  other-extensions:    OverlappingInstances, MultiParamTypeClasses, FlexibleInstances+  build-depends:       base >=4.6 && <4.7, text >=1.1 && <1.2, containers >=0.5 && <0.6, random-fu >=0.2 && <0.3, random-source >=0.3 && <0.4, vector >=0.10 && <0.11, directory >= 1.2 && < 1.4+  -- hs-source-dirs:      +  default-language:    Haskell2010