password 3.0.3.0 → 3.0.4.0
raw patch · 6 files changed
+116/−41 lines, 6 filesdep +cryptondep ~base64
Dependencies added: crypton
Dependency ranges changed: base64
Files
- ChangeLog.md +16/−2
- password.cabal +35/−7
- src/Data/Password/Argon2.hs +7/−0
- src/Data/Password/Internal.hs +13/−0
- src/Data/Password/PBKDF2.hs +20/−14
- src/Data/Password/Scrypt.hs +25/−18
ChangeLog.md view
@@ -1,9 +1,23 @@ # Changelog for `password` +## 3.0.4.0++- Support `base64` package up to and including `base64-1.0`.+- Added the Cabal flags `crypton` and `cryptonite` to choose which dependency to+ build with. Right now the default is `cryptonite` and setting `crypton` changes+ it to `crypton`. Setting the `cryptonite` flag does nothing at the moment, but+ will replace the `crypton` flag in a future major release, so if you want to keep+ using the `cryptonite` package you should start building with this flag.+ When the flags get switched the `crypton` package will be the default and the+ `crypton` flag will turn into a no-op, and you'll have to supply the `cryptonite`+ flag to build with the `cryptonite` package.+ Thanks to [@Vlix](https://github.com/Vlix)+ [#74](https://github.com/cdepillabout/password/pull/74)+ ## 3.0.3.0 -- Added `bcrypt` `defaultParams` used by `hashPassword`- Thanks to [@blackheaven](https://github.com/blackheaven)+- Added `bcrypt` `defaultParams` used by `hashPassword`+ Thanks to [@blackheaven](https://github.com/blackheaven) [#70](https://github.com/cdepillabout/password/pull/70) ## 3.0.2.2
password.cabal view
@@ -1,7 +1,7 @@ cabal-version: 1.12 name: password-version: 3.0.3.0+version: 3.0.4.0 category: Data synopsis: Hashing and checking of passwords description:@@ -47,22 +47,34 @@ ChangeLog.md flag argon2- description: Compile with argon2 support?+ description: Compile with Argon2 support? default: True manual: True flag bcrypt- description: Compile with Scrypt support?+ description: Compile with bcrypt support? default: True manual: True +flag crypton+ description: Use the [crypton] library as the cryptographic backend.+ default: False+ manual: True++flag cryptonite+ description:+ Use the [cryptonite] library as the cryptographic backend.+ (Does nothing until a future major version)+ default: False+ manual: True+ flag pbkdf2 description: Compile with PBKDF2 support? default: True manual: True flag scrypt- description: Compile with Scrypt support?+ description: Compile with scrypt support? default: True manual: True @@ -98,9 +110,8 @@ Data.Password.Internal build-depends: base >= 4.9 && < 5- , base64 >= 0.3 && < 0.5+ , base64 >= 0.3 && < 1.1 , bytestring >= 0.9 && < 0.13- , cryptonite >= 0.15.1 && < 0.31 , memory < 1 , password-types < 2 , template-haskell@@ -109,6 +120,15 @@ -Wall default-language: Haskell2010+ -- At some future major version bump, this should+ -- be changed to the [cryptonite] flag and that+ -- `if flag(cryptonite) build-depends: cryptonite`+ if flag(crypton)+ build-depends:+ crypton >= 0.31 && < 0.35+ else+ build-depends:+ cryptonite >= 0.15.1 && < 0.31 test-suite doctests type:@@ -173,7 +193,6 @@ , base64 , password-types , bytestring- , cryptonite , memory , quickcheck-instances , scrypt@@ -196,3 +215,12 @@ if flag(scrypt) cpp-options: -DCABAL_FLAG_scrypt+ -- At some future major version bump, this should+ -- be changed to the [cryptonite] flag and that+ -- `if flag(cryptonite) build-depends: cryptonite`+ if flag(crypton)+ build-depends:+ crypton+ else+ build-depends:+ cryptonite
src/Data/Password/Argon2.hs view
@@ -74,6 +74,9 @@ import Control.Monad.IO.Class (MonadIO (liftIO)) import Crypto.Error (throwCryptoError) import Crypto.KDF.Argon2 as Argon2 (Options (..), Variant (..), Version (..), hash)+#if MIN_VERSION_base64(1,0,0)+import Data.Base64.Types (extractBase64)+#endif import Data.ByteArray (Bytes, constEq, convert) import Data.ByteString as B (ByteString, length) import Data.ByteString.Base64 (encodeBase64)@@ -205,7 +208,11 @@ , encodeWithoutPadding key ] where+#if MIN_VERSION_base64(1,0,0)+ encodeWithoutPadding = T.dropWhileEnd (== '=') . extractBase64 . encodeBase64+#else encodeWithoutPadding = T.dropWhileEnd (== '=') . encodeBase64+#endif parameters = T.intercalate "," [ "m=" <> showT argon2MemoryCost , "t=" <> showT argon2TimeCost
src/Data/Password/Internal.hs view
@@ -28,7 +28,11 @@ import Crypto.Random (getRandomBytes) import Data.ByteArray (Bytes, convert) import Data.ByteString (ByteString)+#if MIN_VERSION_base64(1,0,0)+import Data.ByteString.Base64 (decodeBase64Untyped)+#else import Data.ByteString.Base64 (decodeBase64)+#endif #if !MIN_VERSION_base(4,13,0) import Data.Semigroup ((<>)) #endif@@ -91,7 +95,11 @@ -- | Decodes a base64 'Text' to a regular 'ByteString' (if possible) from64 :: Text -> Maybe ByteString+#if MIN_VERSION_base64(1,0,0)+from64 = toMaybe . decodeBase64Untyped . encodeUtf8+#else from64 = toMaybe . decodeBase64 . encodeUtf8+#endif where toMaybe = either (const Nothing) Just {-# INLINE from64 #-}@@ -108,7 +116,12 @@ -- | (UNSAFE) Pad a base64 text to "length `rem` 4 == 0" with "=" --+#if MIN_VERSION_base64(1,0,0)+-- >>> import Data.Base64.Types (extractBase64)+-- prop> \bs -> let b64 = extractBase64 (encodeBase64 bs) in unsafePad64 (T.dropWhileEnd (== '=') b64) == b64+#else -- prop> \bs -> let b64 = encodeBase64 bs in unsafePad64 (T.dropWhileEnd (== '=') b64) == b64+#endif unsafePad64 :: Text -> Text unsafePad64 t | remains == 0 = t
src/Data/Password/PBKDF2.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}@@ -72,9 +73,12 @@ import Control.Monad.IO.Class (MonadIO(liftIO)) import Crypto.Hash.Algorithms as Crypto (MD5(..)) import Crypto.KDF.PBKDF2 as PBKDF2+#if MIN_VERSION_base64(1,0,0)+import Data.Base64.Types (extractBase64)+#endif import Data.ByteArray (ByteArray, ByteArrayAccess, Bytes, constEq, convert) import Data.ByteString (ByteString)-import qualified Data.ByteString.Base64 as Base64+import Data.ByteString.Base64 (encodeBase64) import qualified Data.ByteString.Char8 as C8 (length) import Data.Maybe (fromMaybe) import Data.Text (Text)@@ -186,7 +190,11 @@ , b64 key ] where- b64 = Base64.encodeBase64+#if MIN_VERSION_base64(1,0,0)+ b64 = extractBase64 . encodeBase64+#else+ b64 = encodeBase64+#endif key = hashPasswordWithSalt' params s pass -- | Only for internal use@@ -247,18 +255,16 @@ -- "pbkdf2:sha256:150000:etc.etc." let passHash' = fromMaybe passHash $ "pbkdf2:" `T.stripPrefix` passHash paramList = T.split (== ':') passHash'- guard $ length paramList == 4- let [ algT,- iterationsT,- salt64,- hashedKey64 ] = paramList- pbkdf2Algorithm <- textToAlg algT- pbkdf2Iterations <- readT iterationsT- salt <- from64 salt64- hashedKey <- from64 hashedKey64- let pbkdf2OutputLength = fromIntegral $ C8.length hashedKey- pbkdf2Salt = fromIntegral $ C8.length salt- return (PBKDF2Params{..}, Salt salt, hashedKey)+ case paramList of+ [algT, iterationsT, salt64, hashedKey64] -> do+ pbkdf2Algorithm <- textToAlg algT+ pbkdf2Iterations <- readT iterationsT+ salt <- from64 salt64+ hashedKey <- from64 hashedKey64+ let pbkdf2OutputLength = fromIntegral $ C8.length hashedKey+ pbkdf2Salt = fromIntegral $ C8.length salt+ return (PBKDF2Params{..}, Salt salt, hashedKey)+ _ -> Nothing -- | Extracts 'PBKDF2Params' from a 'PasswordHash' 'PBKDF2'. --
src/Data/Password/Scrypt.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-|@@ -65,6 +66,9 @@ import Control.Monad (guard) import Control.Monad.IO.Class (MonadIO(liftIO)) import Crypto.KDF.Scrypt as Scrypt (Parameters(..), generate)+#if MIN_VERSION_base64(1,0,0)+import Data.Base64.Types (extractBase64)+#endif import Data.ByteArray (Bytes, constEq, convert) import Data.ByteString (ByteString) import Data.ByteString.Base64 (encodeBase64)@@ -180,11 +184,16 @@ [ showT scryptRounds , showT scryptBlockSize , showT scryptParallelism- , encodeBase64 salt- , encodeBase64 key+ , toB64 salt+ , toB64 key ] where key = hashPasswordWithSalt' params s pass+#if MIN_VERSION_base64(1,0,0)+ toB64 = extractBase64 . encodeBase64+#else+ toB64 = encodeBase64+#endif -- | Only for internal use hashPasswordWithSalt' :: ScryptParams -> Salt Scrypt -> Password -> ByteString@@ -252,22 +261,20 @@ return PasswordCheckSuccess parseScryptPasswordHashParams :: PasswordHash Scrypt -> Maybe (ScryptParams, Salt Scrypt, ByteString)-parseScryptPasswordHashParams (PasswordHash passHash) = do- let paramList = T.split (== '|') passHash- guard $ length paramList == 5- let [ scryptRoundsT,- scryptBlockSizeT,- scryptParallelismT,- salt64,- hashedKey64 ] = paramList- scryptRounds <- readT scryptRoundsT- scryptBlockSize <- readT scryptBlockSizeT- scryptParallelism <- readT scryptParallelismT- salt <- from64 salt64- hashedKey <- from64 hashedKey64- let scryptOutputLength = fromIntegral $ C8.length hashedKey- scryptSalt = fromIntegral $ C8.length salt- return (ScryptParams{..}, Salt salt, hashedKey)+parseScryptPasswordHashParams (PasswordHash passHash) =+ case paramList of+ [scryptRoundsT, scryptBlockSizeT, scryptParallelismT, salt64, hashedKey64] -> do+ scryptRounds <- readT scryptRoundsT+ scryptBlockSize <- readT scryptBlockSizeT+ scryptParallelism <- readT scryptParallelismT+ salt <- from64 salt64+ hashedKey <- from64 hashedKey64+ let scryptOutputLength = fromIntegral $ C8.length hashedKey+ scryptSalt = fromIntegral $ C8.length salt+ return (ScryptParams{..}, Salt salt, hashedKey)+ _ -> Nothing+ where+ paramList = T.split (== '|') passHash -- | Extracts 'ScryptParams' from a 'PasswordHash' 'Scrypt'. --