pwstore-fast 2.4.1 → 2.4.4
raw patch · 3 files changed
Files
- Crypto/PasswordStore.hs +24/−16
- README.md +2/−0
- pwstore-fast.cabal +3/−3
Crypto/PasswordStore.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings, BangPatterns #-}+{-# LANGUAGE OverloadedStrings, BangPatterns, FlexibleInstances #-} {-# LANGUAGE CPP #-} -- | -- Module : Crypto.PasswordStore@@ -28,17 +28,17 @@ -- The API here is very simple. What you store are called /password hashes/. -- They are strings (technically, ByteStrings) that look like this: ----- > "sha256|14|jEWU94phx4QzNyH94Qp4CQ==|5GEw+jxP/4WLgzt9VS3Ee3nhqBlDsrKiB+rq7JfMckU="+-- > "sha256|17|Ge9pg8a/r4JW356Uux2JHg==|Fdv4jchzDlRAs6WFNUarxLngaittknbaHFFc0k8hAy0=" -- -- Each password hash shows the algorithm, the strength (more on that later), -- the salt, and the hashed-and-salted password. You store these on your server, -- in a database, for when you need to verify a password. You make a password -- hash with the 'makePassword' function. Here's an example: ----- > >>> makePassword "hunter2" 14--- > "sha256|14|Zo4LdZGrv/HYNAUG3q8WcA==|zKjbHZoTpuPLp1lh6ATolWGIKjhXvY4TysuKvqtNFyk="+-- > >>> makePassword "hunter2" 17+-- > "sha256|12|lMzlNz0XK9eiPIYPY96QCQ==|1ZJ/R3qLEF0oCBVNtvNKLwZLpXPM7bLEy/Nc6QBxWro=" ----- This will hash the password @\"hunter2\"@, with strength 12, which is a good+-- This will hash the password @\"hunter2\"@, with strength 17, which is a good -- default value. The strength here determines how long the hashing will -- take. When doing the hashing, we iterate the SHA256 hash function -- @2^strength@ times, so increasing the strength by 1 makes the hashing take@@ -49,8 +49,9 @@ -- the 'IO' monad, you can generate your own salt and pass it to -- 'makePasswordSalt'. ----- Your strength value should not be less than 12, and 14 is a good default--- value at the time of this writing, in 2013.+-- Your strength value should not be less than 16, and 17 is a good default+-- value at the time of this writing, in 2014. OWASP suggests adding 1 to the+-- strength every two years. -- -- Once you've got your password hashes, the second big thing you need to do -- with them is verify passwords against them. When a user gives you a password,@@ -103,6 +104,7 @@ ) where +import qualified Crypto.Hash as CH import qualified Crypto.Hash.SHA256 as H import qualified Data.ByteString.Char8 as B import qualified Data.ByteString as BS@@ -110,8 +112,8 @@ import qualified Data.Binary as Binary import Control.Monad import Control.Monad.ST+import Data.Byteable (Byteable, toBytes, constEqBytes) import Data.STRef-import qualified Data.Digest.Pure.SHA as SHA import Data.Bits import Data.ByteString.Char8 (ByteString) import Data.ByteString.Base64 (encode, decodeLenient)@@ -119,6 +121,10 @@ import System.Random import Data.Maybe import qualified Control.Exception+import Data.Char+import Data.List+import Data.Function+import qualified Data.Foldable as FL --------------------- -- Cryptographic base@@ -150,8 +156,7 @@ -> ByteString -- ^ The encoded message hmacSHA256 secret msg =- let digest = SHA.hmacSha256 (fromStrict secret) (fromStrict msg)- in toStrict . SHA.bytestringDigest $ digest+ toBytes (CH.hmacGetDigest (CH.hmac secret msg) :: CH.Digest CH.SHA256) -- | PBKDF2 key-derivation function. -- For details see @http://tools.ietf.org/html/rfc2898@.@@ -244,7 +249,7 @@ -- High level API ----------------- --- | Hash a password with a given strength (14 is a good default). The output of+-- | Hash a password with a given strength (17 is a good default). The output of -- this function can be written directly to a password file or -- database. Generates a salt using high-quality randomness from -- @\/dev\/urandom@ or (if that is not available, for example on Windows)@@ -255,7 +260,7 @@ -- | A generic version of 'makePassword', which allow the user -- to choose the algorithm to use. ----- >>> makePasswordWith pbkdf1 "password" 14+-- >>> makePasswordWith pbkdf1 "password" 17 -- makePasswordWith :: (ByteString -> Salt -> Int -> ByteString) -- ^ The algorithm to use (e.g. pbkdf1)@@ -287,15 +292,18 @@ makePasswordSaltWith algorithm strengthModifier pwd salt strength = writePwHash (strength, salt, hash) where hash = encode $ algorithm pwd salt (strengthModifier strength) --- | Hash a password with a given strength (14 is a good default), using a given+-- | Hash a password with a given strength (17 is a good default), using a given -- salt. The output of this function can be written directly to a password file -- or database. Example: ----- > >>> makePasswordSalt "hunter2" (makeSalt "72cd18b5ebfe6e96") 14--- > "sha256|14|NzJjZDE4YjVlYmZlNmU5Ng==|yuiNrZW3KHX+pd0sWy9NTTsy5Yopmtx4UYscItSsoxc="+-- > >>> makePasswordSalt "hunter2" (makeSalt "72cd18b5ebfe6e96") 17+-- > "sha256|17|NzJjZDE4YjVlYmZlNmU5Ng==|i5VbJNJ3I6SPnxdK5pL0dHw4FoqnHYpSUXp70coXjOI=" makePasswordSalt :: ByteString -> Salt -> Int -> ByteString makePasswordSalt = makePasswordSaltWith pbkdf1 (2^) +instance Byteable [Char] where+ toBytes = B.pack+ -- | 'verifyPasswordWith' @algorithm userInput pwHash@ verifies -- the password @userInput@ given by the user against the stored password -- hash @pwHash@, with the hashing algorithm @algorithm@. Returns 'True' if the@@ -322,7 +330,7 @@ case readPwHash pwHash of Nothing -> False Just (strength, salt, goodHash) ->- encode (algorithm userInput salt (strengthModifier strength)) == goodHash+ encode (algorithm userInput salt (strengthModifier strength)) `constEqBytes` goodHash -- | Like 'verifyPasswordWith', but uses 'pbkdf1' as algorithm. verifyPassword :: ByteString -> ByteString -> Bool
README.md view
@@ -1,3 +1,5 @@+[](https://travis-ci.org/PeterScott/pwstore)+ Storing passwords securely in Haskell =======================
pwstore-fast.cabal view
@@ -1,5 +1,5 @@ Name: pwstore-fast-Version: 2.4.1+Version: 2.4.4 Synopsis: Secure password storage. Description: To store passwords securely, they should be salted, then hashed with a slow hash function. This library@@ -30,7 +30,7 @@ Build-depends: base >= 4, base < 5, bytestring >= 0.9, base64-bytestring >= 0.1, binary >= 0.5,- SHA >= 1.6.1,- cryptohash >= 0.6, random >= 1+ cryptohash >= 0.6, random >= 1,+ byteable >= 0.1 ghc-options: -Wall