Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion password/ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# Changelog for `password`

## 3.1.1.0

- Support `crypton` dependency to include `^>= 1.1.0`.
- Removed converting to and from `Bytes`, especially since `ram >= 0.21.0`
(a dependency of `crypton >= 1.1`) has it as a newtype over `ByteString`.
Thanks to [@Vlix](https://github.com/Vlix)
[#91](https://github.com/cdepillabout/password/pull/91)

## 3.1.0.2

- Added reference to [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli) package in modules and README.

## 3.1.0.1

- Redo the conditionals in the `password.cabal` file so that the scrypt
- Redo the conditionals in the `password.cabal` file so that the `scrypt`
library is only included as a test dependency on `x86_64`. This generally
shouldn't affect users of the `password` library.
Thanks to [@sternenseemann](https://github.com/sternenseemann)
Expand Down
24 changes: 19 additions & 5 deletions password/password.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 1.12

name: password
version: 3.1.0.2
version: 3.1.1.0
category: Security
synopsis: Hashing and checking of passwords
description:
Expand Down Expand Up @@ -79,6 +79,13 @@ flag scrypt
default: True
manual: True

flag memory
description: Compile with [memory] dependency instead of [ram]
default: False
-- This should NOT be manual, so that constraint solvers
-- can figure out which version of 'crypton' is used.
manual: False

custom-setup
setup-depends:
base < 5
Expand Down Expand Up @@ -113,20 +120,27 @@ library
base >= 4.9 && < 5
, base64 >= 0.3 && < 1.1
, bytestring >= 0.9 && < 0.13
, memory < 1
, password-types < 2
, template-haskell >= 2.2 && < 3
, text >= 1.2.2 && < 3
ghc-options:
-Wall
default-language:
Haskell2010
-- 'cryptonite' always means 'memory'
if flag(cryptonite)
build-depends:
cryptonite >= 0.15.1 && < 0.31
cryptonite >= 0.15.1 && < 0.31,
memory < 1
else
build-depends:
crypton >= 0.31 && < 1.1
if flag(memory)
build-depends:
crypton >= 0.31 && < 1.1,
memory < 1
else
build-depends:
crypton >= 1.1 && < 1.2,
ram < 1

test-suite doctests
type:
Expand Down
13 changes: 6 additions & 7 deletions password/src/Data/Password/Argon2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ import Crypto.KDF.Argon2 as Argon2 (Options (..), Variant (..), Version (..), ha
#if MIN_VERSION_base64(1,0,0)
import Data.Base64.Types (extractBase64)
#endif
import Data.ByteArray (Bytes, constEq, convert)
import Data.ByteArray (constEq)
import Data.ByteString as B (ByteString, length)
import Data.ByteString.Base64 (encodeBase64)
import Data.Maybe (fromMaybe)
#if !MIN_VERSION_base(4,13,0)
import Data.Semigroup ((<>))
#endif
import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Text as T (dropWhileEnd, intercalate, split, splitAt, stripPrefix)
import Data.Word (Word32)

Expand All @@ -102,7 +103,6 @@ import Data.Password.Internal (
from64,
readT,
showT,
toBytes,
unsafePad64,
)
import Data.Password.Types (
Expand Down Expand Up @@ -232,14 +232,13 @@ hashPasswordWithSalt params@Argon2Params{..} s@(Salt salt) pass =
-- | Only for internal use
hashPasswordWithSalt' :: Argon2Params -> Salt Argon2 -> Password -> ByteString
hashPasswordWithSalt' Argon2Params{..} (Salt salt) pass =
convert (argon2Hash :: Bytes)
where
argon2Hash = throwCryptoError $
throwCryptoError $
Argon2.hash
options
(toBytes $ unsafeShowPassword pass)
(convert salt :: Bytes)
(encodeUtf8 $ unsafeShowPassword pass)
salt
$ fromIntegral argon2OutputLength
where
options = Argon2.Options {
iterations = argon2TimeCost,
memory = argon2MemoryCost,
Expand Down
18 changes: 7 additions & 11 deletions password/src/Data/Password/Bcrypt.hs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ module Data.Password.Bcrypt (
import Control.Monad (guard)
import Control.Monad.IO.Class (MonadIO(liftIO))
import Crypto.KDF.BCrypt as Bcrypt (bcrypt, validatePassword)
import Data.ByteArray (Bytes, convert)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
import Text.Read (readMaybe)

import Data.Password.Types (
Expand All @@ -97,11 +97,7 @@ import Data.Password.Types (
, unsafeShowPassword
, Salt(..)
)
import Data.Password.Internal (
PasswordCheck(..)
, fromBytes
, toBytes
)
import Data.Password.Internal (PasswordCheck(..))
import qualified Data.Password.Internal (newSalt)


Expand Down Expand Up @@ -169,9 +165,9 @@ hashPasswordWithSalt
hashPasswordWithSalt cost (Salt salt) pass =
let hash = Bcrypt.bcrypt
cost
(convert salt :: Bytes)
(toBytes $ unsafeShowPassword pass)
in PasswordHash $ fromBytes hash
salt
(encodeUtf8 $ unsafeShowPassword pass)
in PasswordHash $ decodeUtf8 hash

-- | Hash a password using the /bcrypt/ algorithm with the given cost.
--
Expand Down Expand Up @@ -214,8 +210,8 @@ hashPasswordWithParams cost pass = liftIO $ do
checkPassword :: Password -> PasswordHash Bcrypt -> PasswordCheck
checkPassword pass (PasswordHash passHash) =
if Bcrypt.validatePassword
(toBytes $ unsafeShowPassword pass)
(toBytes passHash)
(encodeUtf8 $ unsafeShowPassword pass)
(encodeUtf8 passHash)
then PasswordCheckSuccess
else PasswordCheckFail

Expand Down
15 changes: 1 addition & 14 deletions password/src/Data/Password/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ module Data.Password.Internal (
PasswordCheck(..)
, newSalt
-- * Utility
, toBytes
, fromBytes
, from64
, unsafePad64
, readT
Expand All @@ -26,7 +24,6 @@ module Data.Password.Internal (

import Control.Monad.IO.Class (MonadIO (liftIO))
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)
Expand All @@ -44,7 +41,7 @@ import Data.Text as T (
unpack,
)
import Data.Password.Types (Salt(..))
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Text.Encoding (encodeUtf8)
import Text.Read (readMaybe)

-- $setup
Expand Down Expand Up @@ -83,16 +80,6 @@ data PasswordCheck
-- hashed password.
deriving (Eq, Read, Show)

-- | Converting 'Text' to 'Bytes'
toBytes :: Text -> Bytes
toBytes = convert . encodeUtf8
{-# INLINE toBytes #-}

-- | Converting 'Bytes' to 'Text'
fromBytes :: Bytes -> Text
fromBytes = decodeUtf8 . convert
{-# INLINE fromBytes #-}

-- | Decodes a base64 'Text' to a regular 'ByteString' (if possible)
from64 :: Text -> Maybe ByteString
#if MIN_VERSION_base64(1,0,0)
Expand Down
22 changes: 8 additions & 14 deletions password/src/Data/Password/PBKDF2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,14 @@ 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.ByteArray (constEq)
import Data.ByteString (ByteString)
import Data.ByteString.Base64 (encodeBase64)
import qualified Data.ByteString.Char8 as C8 (length)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T (intercalate, pack, split, stripPrefix)
import Data.Text.Encoding (encodeUtf8)
import Data.Word (Word32)

import Data.Password.Types (
Expand All @@ -101,12 +102,7 @@ import Data.Password.Types (
, unsafeShowPassword
, Salt(..)
)
import Data.Password.Internal (
PasswordCheck(..)
, from64
, readT
, toBytes
)
import Data.Password.Internal (PasswordCheck(..), from64, readT)
import qualified Data.Password.Internal (newSalt)


Expand Down Expand Up @@ -209,13 +205,12 @@ hashPasswordWithSalt params@PBKDF2Params{..} s@(Salt salt) pass =
-- | Only for internal use
hashPasswordWithSalt' :: PBKDF2Params -> Salt PBKDF2 -> Password -> ByteString
hashPasswordWithSalt' PBKDF2Params{..} (Salt salt) pass =
convert (pbkdf2Hash :: Bytes)
where
pbkdf2Hash = algToFunc
algToFunc
pbkdf2Algorithm
params
(toBytes $ unsafeShowPassword pass)
(convert salt :: Bytes)
(encodeUtf8 $ unsafeShowPassword pass)
salt
where
params = PBKDF2.Parameters {
PBKDF2.iterCounts = fromIntegral pbkdf2Iterations,
PBKDF2.outputLength = fromIntegral $ maxOutputLength pbkdf2Algorithm pbkdf2OutputLength
Expand Down Expand Up @@ -324,8 +319,7 @@ textToAlg = \case
_ -> Nothing

-- Which function to use, based on the given algorithm
algToFunc :: (ByteArrayAccess password, ByteArrayAccess salt, ByteArray hash)
=> PBKDF2Algorithm -> PBKDF2.Parameters -> password -> salt -> hash
algToFunc :: PBKDF2Algorithm -> PBKDF2.Parameters -> ByteString -> ByteString -> ByteString
algToFunc = \case
PBKDF2_MD5 -> PBKDF2.generate (PBKDF2.prfHMAC Crypto.MD5)
PBKDF2_SHA1 -> PBKDF2.fastPBKDF2_SHA1
Expand Down
13 changes: 6 additions & 7 deletions password/src/Data/Password/Scrypt.hs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ 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.ByteArray (constEq)
import Data.ByteString (ByteString)
import Data.ByteString.Base64 (encodeBase64)
import qualified Data.ByteString.Char8 as C8 (length)
import Data.Maybe (fromMaybe)
import qualified Data.Text as T (intercalate, split)
import Data.Text.Encoding (encodeUtf8)
import Data.Word (Word32)

import Data.Password.Types (
Expand All @@ -98,7 +99,6 @@ import Data.Password.Internal (
, from64
, readT
, showT
, toBytes
)
import qualified Data.Password.Internal (newSalt)

Expand Down Expand Up @@ -207,12 +207,11 @@ hashPasswordWithSalt params@ScryptParams{..} s@(Salt salt) pass =
-- | Only for internal use
hashPasswordWithSalt' :: ScryptParams -> Salt Scrypt -> Password -> ByteString
hashPasswordWithSalt' ScryptParams{..} (Salt salt) pass =
convert (scryptHash :: Bytes)
where
scryptHash = Scrypt.generate
Scrypt.generate
params
(toBytes $ unsafeShowPassword pass)
(convert salt :: Bytes)
(encodeUtf8 $ unsafeShowPassword pass)
salt
where
params = Scrypt.Parameters {
n = 2 ^ scryptRounds,
r = fromIntegral scryptBlockSize,
Expand Down
Loading