diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,35 @@
 # Changelog for `password`
 
+## 3.1.1.0
+
+-   Support `crypton` dependency to include `^>= 1.1.0`.
+    Added the `memory-dep` flag to be able to enforce building with `memory`
+    instead of `ram` when constrained to lower versions of `crypton`.
+-   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`
+    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)
+    [#85](https://github.com/cdepillabout/password/pull/85)
+
+## 3.1.0.0
+
+-   Switched default cryptographic backend library from `cryptonite` to `crypton`.
+    The `crypton` flag is now a no-op, and the `cryptonite` flag is needed to build
+    the `password` library using the `cryptonite` library.
+    Thanks to [@Vlix](https://github.com/Vlix)
+    [#81](https://github.com/cdepillabout/password/pull/81)
+
 ## 3.0.4.0
 
 -   Support `base64` package up to and including `base64-1.0`.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 
 This library provides functions for working with passwords and password hashes in Haskell.
 
-Currently supports the following algorithms:
+It currently supports the following algorithms:
 
 * `PBKDF2`
 * `bcrypt`
@@ -17,3 +17,5 @@
 
 Also, see the [password-instances](https://hackage.haskell.org/package/password-instances)
 package for instances for common typeclasses.
+
+To quickly test and use `password`, you can use [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli).
diff --git a/password.cabal b/password.cabal
--- a/password.cabal
+++ b/password.cabal
@@ -1,8 +1,8 @@
 cabal-version: 1.12
 
 name:           password
-version:        3.0.4.0
-category:       Data
+version:        3.1.1.0
+category:       Security
 synopsis:       Hashing and checking of passwords
 description:
     A library providing functionality for working with plain-text and hashed passwords
@@ -45,6 +45,7 @@
 extra-source-files:
     README.md
     ChangeLog.md
+    test/golden/*.golden
 
 flag argon2
   description: Compile with Argon2 support?
@@ -58,16 +59,23 @@
 
 flag crypton
   description: Use the [crypton] library as the cryptographic backend.
+    (Does nothing since version 3.1.0.0; might be removed in a future major version)
   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 memory-dep
+  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
+
 flag pbkdf2
   description: Compile with PBKDF2 support?
   default: True
@@ -80,9 +88,9 @@
 
 custom-setup
   setup-depends:
-      base                      <5
-    , Cabal                     <4
-    , cabal-doctest  >=1.0.6 && <1.1
+      base                       < 5
+    , Cabal                      < 4
+    , cabal-doctest  >= 1.0.6 && < 1.1
 
 source-repository head
   type: git
@@ -112,23 +120,27 @@
       base        >= 4.9      && < 5
     , base64      >= 0.3      && < 1.1
     , bytestring  >= 0.9      && < 0.13
-    , memory                     < 1
     , password-types             < 2
-    , template-haskell
+    , template-haskell >= 2.2 && < 3
     , text        >= 1.2.2    && < 3
   ghc-options:
       -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)
+  -- 'cryptonite' always means 'memory'
+  if flag(cryptonite)
     build-depends:
-      crypton     >= 0.31   && < 0.35
+      cryptonite >= 0.15.1 && < 0.31,
+      memory < 1
   else
-    build-depends:
-      cryptonite  >= 0.15.1   && < 0.31
+    if flag(memory-dep)
+      build-depends:
+        crypton >= 0.31 && < 1.1,
+        memory < 1
+    else
+      build-depends:
+        crypton >= 1.1 && < 1.2,
+        ram < 1
 
 test-suite doctests
   type:
@@ -140,13 +152,11 @@
   ghc-options:
       -threaded -O2 -rtsopts -with-rtsopts=-N
   build-depends:
-      base >=4.9 && <5
+      base >= 4.9 && < 5
     , base-compat
     , doctest
-    , password
     , QuickCheck
     , quickcheck-instances
-    , template-haskell
   default-language:
       Haskell2010
 
@@ -158,6 +168,7 @@
       test/tasty
   main-is:
       Spec.hs
+
   other-modules:
       Data.Password.Internal
     -- We're also putting all the modules from
@@ -186,41 +197,51 @@
     other-modules:
       Scrypt
       Data.Password.Scrypt
+
   ghc-options:
       -threaded -O2 -rtsopts -with-rtsopts=-N
+
   build-depends:
-      base >=4.9 && <5
+      base >= 4.9 && < 5
     , base64
     , password-types
     , bytestring
     , memory
     , quickcheck-instances
-    , scrypt
     , tasty
     , tasty-hunit
+    , tasty-golden
     , tasty-quickcheck
     , template-haskell
     , text
   default-language:
       Haskell2010
+
   if flag(argon2)
     cpp-options:
       -DCABAL_FLAG_argon2
+
   if flag(bcrypt)
     cpp-options:
       -DCABAL_FLAG_bcrypt
+
   if flag(pbkdf2)
     cpp-options:
       -DCABAL_FLAG_pbkdf2
+
   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)
+
+    -- The scrypt package is optionally used in tests to ensure compatibility
+    -- between password and scrypt.  However, scrypt requires the x86_64 arch
+    -- with the SSE2 instruction set.
+    if arch(x86_64)
+      build-depends: scrypt
+
+  if flag(cryptonite)
     build-depends:
-      crypton
+      cryptonite
   else
     build-depends:
-      cryptonite
+      crypton
diff --git a/src/Data/Password/Argon2.hs b/src/Data/Password/Argon2.hs
--- a/src/Data/Password/Argon2.hs
+++ b/src/Data/Password/Argon2.hs
@@ -33,6 +33,15 @@
 It is, however, recommended over @'Data.Password.Scrypt.Scrypt'@ most of the time,
 and it also seems like it might become the go-to password algorithm if no
 vulnarabilities are discovered within the next couple of years.
+
+== Testing
+
+You can use [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli) to test it:
+
+> $ password-cli check argon2 --hash 'SOME-HASH'
+
+> $ password-cli hash argon2 --password-file password.txt
+
 -}
 
 -- I think the portability is broadened to
@@ -77,7 +86,7 @@
 #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)
@@ -85,6 +94,7 @@
 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)
 
@@ -93,7 +103,6 @@
     from64,
     readT,
     showT,
-    toBytes,
     unsafePad64,
  )
 import Data.Password.Types (
@@ -223,14 +232,13 @@
 -- | 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,
diff --git a/src/Data/Password/Bcrypt.hs b/src/Data/Password/Bcrypt.hs
--- a/src/Data/Password/Bcrypt.hs
+++ b/src/Data/Password/Bcrypt.hs
@@ -42,6 +42,15 @@
 because of the 1 character-long "$2$" version prefix, @bcrypt@ has had a version increase shortly
 after release, turning the prefix into a 2 character-long one like "$2a$" pretty
 much from the very beginning.
+
+== Testing
+
+You can use [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli) to test it:
+
+> $ password-cli check bcrypt --hash 'SOME-HASH'
+
+> $ password-cli hash bcrypt --password-file password.txt
+
 -}
 
 module Data.Password.Bcrypt (
@@ -77,8 +86,8 @@
 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 (
@@ -88,11 +97,7 @@
   , unsafeShowPassword
   , Salt(..)
   )
-import Data.Password.Internal (
-    PasswordCheck(..)
-  , fromBytes
-  , toBytes
-  )
+import Data.Password.Internal (PasswordCheck(..))
 import qualified Data.Password.Internal (newSalt)
 
 
@@ -160,9 +165,9 @@
 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.
 --
@@ -205,8 +210,8 @@
 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
 
@@ -221,8 +226,11 @@
 extractParams :: PasswordHash Bcrypt -> Maybe Int
 extractParams (PasswordHash passHash) =
   case T.split (== '$') passHash of
-    [_, version, cost, _pass] -> do
-      guard $ elem version $ map T.pack ["2", "2a", "2x", "2y", "2b"]
+    [prefix, version, cost, _pass] -> do
+      guard $
+        -- 'prefix' should be nothing, because the hash should start with a '$'
+        -- The order of versions is based on most likely to encounter in the wild.
+        T.null prefix && elem version (T.pack <$> ["2b", "2y", "2x", "2a", "2"])
       readMaybe $ T.unpack cost
     _ -> Nothing
 
diff --git a/src/Data/Password/Internal.hs b/src/Data/Password/Internal.hs
--- a/src/Data/Password/Internal.hs
+++ b/src/Data/Password/Internal.hs
@@ -14,8 +14,6 @@
     PasswordCheck(..)
   , newSalt
   -- * Utility
-  , toBytes
-  , fromBytes
   , from64
   , unsafePad64
   , readT
@@ -26,7 +24,6 @@
 
 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)
@@ -44,7 +41,7 @@
     unpack,
  )
 import Data.Password.Types (Salt(..))
-import Data.Text.Encoding (decodeUtf8, encodeUtf8)
+import Data.Text.Encoding (encodeUtf8)
 import Text.Read (readMaybe)
 
 -- $setup
@@ -82,16 +79,6 @@
   -- ^ The password check failed. The plain-text password does not match the
   -- 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
diff --git a/src/Data/Password/PBKDF2.hs b/src/Data/Password/PBKDF2.hs
--- a/src/Data/Password/PBKDF2.hs
+++ b/src/Data/Password/PBKDF2.hs
@@ -35,6 +35,15 @@
 would probably be the safest option, as it has no memory cost which
 could become a problem if not properly calibrated to the machine
 doing the password verifications.
+
+== Testing
+
+You can use [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli) to test it:
+
+> $ password-cli check pbkdf2 --hash 'SOME-HASH'
+
+> $ password-cli hash pbkdf2 --password-file password.txt
+
 -}
 
 module Data.Password.PBKDF2 (
@@ -76,13 +85,14 @@
 #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 (
@@ -92,12 +102,7 @@
   , unsafeShowPassword
   , Salt(..)
   )
-import Data.Password.Internal (
-    PasswordCheck(..)
-  , from64
-  , readT
-  , toBytes
-  )
+import Data.Password.Internal (PasswordCheck(..), from64, readT)
 import qualified Data.Password.Internal (newSalt)
 
 
@@ -200,13 +205,12 @@
 -- | 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
@@ -315,8 +319,7 @@
   _ -> 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
diff --git a/src/Data/Password/Scrypt.hs b/src/Data/Password/Scrypt.hs
--- a/src/Data/Password/Scrypt.hs
+++ b/src/Data/Password/Scrypt.hs
@@ -30,6 +30,15 @@
 Because of the memory cost, it is generally advised to use
 @'Data.Password.Bcrypt.Bcrypt'@ if you're not sure this might be a
 problem on your system.
+
+== Testing
+
+You can use [password-cli](https://github.com/cdepillabout/password/tree/master/password-cli) to test it:
+
+> $ password-cli check scrypt --hash 'SOME-HASH'
+
+> $ password-cli hash scrypt --password-file password.txt
+
 -}
 
 module Data.Password.Scrypt (
@@ -69,12 +78,13 @@
 #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 (
@@ -89,7 +99,6 @@
   , from64
   , readT
   , showT
-  , toBytes
   )
 import qualified Data.Password.Internal (newSalt)
 
@@ -198,12 +207,11 @@
 -- | 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,
diff --git a/src/Data/Password/Validate.hs b/src/Data/Password/Validate.hs
--- a/src/Data/Password/Validate.hs
+++ b/src/Data/Password/Validate.hs
@@ -202,8 +202,9 @@
 
 import Data.Char (chr, isAsciiLower, isAsciiUpper, isDigit, ord)
 import Data.Function (on)
-import Data.List (foldl')
-
+#if !MIN_VERSION_base(4,20,0)
+import Data.Foldable (foldl')
+#endif
 import Data.Text (Text)
 import qualified Data.Text as T
 import Language.Haskell.TH (Exp, Q, appE)
diff --git a/test/golden/Argon_defaultParams.golden b/test/golden/Argon_defaultParams.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Argon_defaultParams.golden
@@ -0,0 +1,1 @@
+$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ0Mg$w9lYrby3BP07ISb/6DWrawOF7lP9EZZfSBV2SiukgSE
diff --git a/test/golden/Argon_otherSalt.golden b/test/golden/Argon_otherSalt.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Argon_otherSalt.golden
@@ -0,0 +1,1 @@
+$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQw$4ZXadpbypzQxRQe2bef8kyFJc0PWKBHXoA5FN4iXf20
diff --git a/test/golden/Argon_outputLength24.golden b/test/golden/Argon_outputLength24.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Argon_outputLength24.golden
@@ -0,0 +1,1 @@
+$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ0Mg$jr2U2k4fMCMYkjLZTi8264BWKmovscHJ
diff --git a/test/golden/Argon_variantArgon2i.golden b/test/golden/Argon_variantArgon2i.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Argon_variantArgon2i.golden
@@ -0,0 +1,1 @@
+$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ0Mg$wTEHt+UirwtEfvpsYyNNCosby+3w651waXa3dtyF3Fo
diff --git a/test/golden/Bcrypt_cost16.golden b/test/golden/Bcrypt_cost16.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Bcrypt_cost16.golden
@@ -0,0 +1,1 @@
+$2b$16$a07rXVLfZFOuKB.uKB.yKeckTbSjjG2z2Hz8Kb2s8Jsc82snjBHxm
diff --git a/test/golden/Bcrypt_cost4.golden b/test/golden/Bcrypt_cost4.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Bcrypt_cost4.golden
@@ -0,0 +1,1 @@
+$2b$04$a07rXVLfZFOuKB.uKB.yKe1sTwXsMijp7DB/Yz0JJk2mmZqbRc6p2
diff --git a/test/golden/Bcrypt_defaultParams.golden b/test/golden/Bcrypt_defaultParams.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Bcrypt_defaultParams.golden
@@ -0,0 +1,1 @@
+$2b$10$a07rXVLfZFOuKB.uKB.yKe1tQQIacGVaKJqgpYw212LZlYsLIMonK
diff --git a/test/golden/Bcrypt_otherSalt.golden b/test/golden/Bcrypt_otherSalt.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Bcrypt_otherSalt.golden
@@ -0,0 +1,1 @@
+$2b$10$a07rXVLfZFOuKB.uKB.uK.yahNLJ/XzWDg41m2qdAMMEpkL7RrFG.
diff --git a/test/golden/PBKDF2_algorithmMD5.golden b/test/golden/PBKDF2_algorithmMD5.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/PBKDF2_algorithmMD5.golden
@@ -0,0 +1,1 @@
+md5:25000:c29tZXNhbHQ0Mg==:jiOmE1hpAp2eJwrJFbJPLw==
diff --git a/test/golden/PBKDF2_defaultParams.golden b/test/golden/PBKDF2_defaultParams.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/PBKDF2_defaultParams.golden
@@ -0,0 +1,1 @@
+sha512:25000:c29tZXNhbHQ0Mg==:RUT4QuEfyBnGIUR3R1jXbD+MjSTU+dNOLWX0mNtLKGI03PIjmxYSIN6USII99OMMhI3KR4o0tVJ1DH8XZaCtbA==
diff --git a/test/golden/PBKDF2_iterCounts1000.golden b/test/golden/PBKDF2_iterCounts1000.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/PBKDF2_iterCounts1000.golden
@@ -0,0 +1,1 @@
+sha512:1000:c29tZXNhbHQ0Mg==:1gWOWLAgx5ojc3rh9uegFTRyUgKYHS84GPARbqZYIyHeAZdRQzVOLaEAg00JxeglImCAYZbBZ/dBh0Al8q1d8Q==
diff --git a/test/golden/PBKDF2_otherSalt.golden b/test/golden/PBKDF2_otherSalt.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/PBKDF2_otherSalt.golden
@@ -0,0 +1,1 @@
+sha512:25000:c29tZXNhbHQw:SjeECOnuJvRIgLwPtL/akEzSS/+5vI4ZNRxEnZUOHnDuubUg7FcIuhnwm8a9cvuOXQrqsCZPHGgh8LNpxLEvRg==
diff --git a/test/golden/PBKDF2_outputLength16.golden b/test/golden/PBKDF2_outputLength16.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/PBKDF2_outputLength16.golden
@@ -0,0 +1,1 @@
+sha512:25000:c29tZXNhbHQ0Mg==:RUT4QuEfyBnGIUR3R1jXbA==
diff --git a/test/golden/Scrypt_defaultParams.golden b/test/golden/Scrypt_defaultParams.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Scrypt_defaultParams.golden
@@ -0,0 +1,1 @@
+14|8|1|c29tZXNhbHQ0Mg==|byRql1IUuO27GSmCJ0a6ce18VJ6DwIdEcVNvvdEDFBFXosA4Vqh3SES/rR0+pY6ntCTWq4GZlQGTY67TWvWI1A==
diff --git a/test/golden/Scrypt_otherSalt.golden b/test/golden/Scrypt_otherSalt.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Scrypt_otherSalt.golden
@@ -0,0 +1,1 @@
+14|8|1|c29tZXNhbHQw|us1zh+3aNbwanYjy6Ig+Ft8yAv741HCMOemJpSEP2OJSic/hwr75xCeGVGqU9yG5NUnDAZ1arPuwBkVRgdLemA==
diff --git a/test/golden/Scrypt_outputLength16.golden b/test/golden/Scrypt_outputLength16.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Scrypt_outputLength16.golden
@@ -0,0 +1,1 @@
+14|8|1|c29tZXNhbHQ0Mg==|byRql1IUuO27GSmCJ0a6cQ==
diff --git a/test/golden/Scrypt_rounds8.golden b/test/golden/Scrypt_rounds8.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Scrypt_rounds8.golden
@@ -0,0 +1,1 @@
+8|8|1|c29tZXNhbHQ0Mg==|XgnxMJ3Ecu5nfvZUyHX7sCxRWRwmeyXeRpqwMy1jCGyPZCYJdGaS0fSJbenFgRoWTFqRWaJ1SoxnpWIiUIyrPw==
diff --git a/test/golden/Scrypt_saltLength16.golden b/test/golden/Scrypt_saltLength16.golden
new file mode 100644
--- /dev/null
+++ b/test/golden/Scrypt_saltLength16.golden
@@ -0,0 +1,1 @@
+14|8|1|c29tZXNhbHQ0Mg==|byRql1IUuO27GSmCJ0a6ce18VJ6DwIdEcVNvvdEDFBFXosA4Vqh3SES/rR0+pY6ntCTWq4GZlQGTY67TWvWI1A==
diff --git a/test/tasty/Argon2.hs b/test/tasty/Argon2.hs
--- a/test/tasty/Argon2.hs
+++ b/test/tasty/Argon2.hs
@@ -1,8 +1,11 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Argon2 (testArgon2) where
 
+import Data.ByteString.Lazy (fromStrict)
+import Data.Text.Encoding (encodeUtf8)
 import Test.Tasty (TestTree, testGroup)
 import Test.Tasty.HUnit (assertBool, assertEqual, testCase)
+import Test.Tasty.Golden (goldenVsString)
 
 import Data.Password.Argon2
 
@@ -24,6 +27,7 @@
   , testWithParams "Argon2 (Argon2d)" (fastParams{ argon2Variant = Argon2d })
   , paddingTests
   , omittedVersionTest
+  , testGolden
   ]
   where
     testWithParams s params =
@@ -86,3 +90,16 @@
 v10Hash, v10HashWithoutVersion :: PasswordHash Argon2
 v10Hash          = PasswordHash "$argon2i$v=16$m=65536,t=2,p=1$Kx1BEcpIg0Ey5GyXq5do2w$0qRfWHw09EdqQkSsaG57O/ou8v/E6Vc83w"
 v10HashWithoutVersion = PasswordHash "$argon2i$m=65536,t=2,p=1$Kx1BEcpIg0Ey5GyXq5do2w$0qRfWHw09EdqQkSsaG57O/ou8v/E6Vc83w"
+
+testGolden :: TestTree
+testGolden = testGroup "Golden tests"
+    [ go "defaultParams" "Argon_defaultParams" defaultParams "somesalt42"
+    , go "variant = Argon2i" "Argon_variantArgon2i" defaultParams{argon2Variant = Argon2i} "somesalt42"
+    , go "output length = 24" "Argon_outputLength24" defaultParams{argon2OutputLength = 24} "somesalt42"
+    , go "other salt" "Argon_otherSalt" defaultParams "somesalt0"
+    ]
+  where go testName fileName params salt =
+          goldenVsString
+            testName
+            ("test/golden/" <> fileName <> ".golden")
+            (return $ fromStrict $ encodeUtf8 $ unPasswordHash $ hashPasswordWithSalt params (Salt salt) $ mkPassword "password")
diff --git a/test/tasty/Bcrypt.hs b/test/tasty/Bcrypt.hs
--- a/test/tasty/Bcrypt.hs
+++ b/test/tasty/Bcrypt.hs
@@ -1,9 +1,12 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Bcrypt where
 
+import Data.ByteString.Lazy (fromStrict)
 import Data.Text (pack)
+import Data.Text.Encoding (encodeUtf8)
 import Test.Tasty
 import Test.Tasty.HUnit (testCase, assertEqual)
+import Test.Tasty.Golden (goldenVsString)
 
 import Data.Password.Bcrypt
 
@@ -22,6 +25,7 @@
 -- These apparently do not work.
 --   , testPassword "2x"
 --   , testPassword "2"
+  , testGolden
   ]
 
 -- | Tests if the version does not matter for matching the hash.
@@ -34,3 +38,16 @@
   where
     hash v = PasswordHash $
         "$" <> pack v <> "$10$v0mMyoUN2ZvDqsJFPH6ft.FcpX67hdXhh7tWf8/hwWZrKZ8U2Phs6"
+
+testGolden :: TestTree
+testGolden = testGroup "Golden tests"
+    [ go "defaultParams" "Bcrypt_defaultParams" defaultParams "somesalt00000042"
+    , go "cost = 16" "Bcrypt_cost16" 16 "somesalt00000042"
+    , go "cost = 4" "Bcrypt_cost4" 4 "somesalt00000042"
+    , go "other salt" "Bcrypt_otherSalt" defaultParams "somesalt00000000"
+    ]
+  where go testName fileName params salt =
+          goldenVsString
+            testName
+            ("test/golden/" <> fileName <> ".golden")
+            (return $ fromStrict $ encodeUtf8 $ unPasswordHash $ hashPasswordWithSalt params (Salt salt) $ mkPassword "password")
diff --git a/test/tasty/PBKDF2.hs b/test/tasty/PBKDF2.hs
--- a/test/tasty/PBKDF2.hs
+++ b/test/tasty/PBKDF2.hs
@@ -5,10 +5,13 @@
 import Crypto.Hash.Algorithms as Crypto (HashAlgorithm, SHA1(..), SHA256(..), SHA512(..))
 import Crypto.KDF.PBKDF2 as PBKDF2
 import Data.ByteString (ByteString)
+import Data.ByteString.Lazy (fromStrict)
 #if !MIN_VERSION_base(4,13,0)
 import Data.Semigroup ((<>))
 #endif
+import Data.Text.Encoding (encodeUtf8)
 import Test.Tasty
+import Test.Tasty.Golden (goldenVsString)
 import Test.Tasty.QuickCheck
 import Test.QuickCheck.Instances.ByteString ()
 import Test.QuickCheck.Instances.Text ()
@@ -43,6 +46,7 @@
       (\pass (PasswordHash hash) -> checkPassword pass . PasswordHash $ "pbkdf2:" <> hash)
       extractParams
       testParams
+  , testGolden
   ]
   where
     testIt s params = testCorrectPassword s (hashPasswordWithParams params) checkPassword extractParams params
@@ -65,3 +69,17 @@
     PBKDF2.iterCounts = 2000,
     PBKDF2.outputLength = i
   }
+
+testGolden :: TestTree
+testGolden = testGroup "Golden tests"
+    [ go "defaultParams" "PBKDF2_defaultParams" defaultParams "somesalt42"
+    , go "algorithm = MD5" "PBKDF2_algorithmMD5" defaultParams{pbkdf2Algorithm = PBKDF2_MD5} "somesalt42"
+    , go "output length = 16" "PBKDF2_outputLength16" defaultParams{pbkdf2OutputLength = 16} "somesalt42"
+    , go "iterCounts = 1000" "PBKDF2_iterCounts1000" defaultParams{pbkdf2Iterations = 1000} "somesalt42"
+    , go "other salt" "PBKDF2_otherSalt" defaultParams "somesalt0"
+    ]
+  where go testName fileName params salt =
+          goldenVsString
+            testName
+            ("test/golden/" <> fileName <> ".golden")
+            (return $ fromStrict $ encodeUtf8 $ unPasswordHash $ hashPasswordWithSalt params (Salt salt) $ mkPassword "password")
diff --git a/test/tasty/Scrypt.hs b/test/tasty/Scrypt.hs
--- a/test/tasty/Scrypt.hs
+++ b/test/tasty/Scrypt.hs
@@ -1,13 +1,20 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
 module Scrypt where
 
+import Data.ByteString.Lazy (fromStrict)
 import Data.Maybe (fromJust)
 import Data.Text (Text)
 import Data.Text.Encoding (encodeUtf8)
 import Test.Tasty
+import Test.Tasty.Golden (goldenVsString)
 import Test.Tasty.QuickCheck
 import Test.QuickCheck.Instances.Text ()
 
+#ifdef x86_64_HOST_ARCH
 import qualified Crypto.Scrypt as Scrypt
+#endif
+
 import Data.Password.Types
 import Data.Password.Scrypt
 
@@ -24,7 +31,10 @@
                  checkPassword
                  extractParams
                  testsParams8Rounds
+#ifdef x86_64_HOST_ARCH
   , testProperty "scrypt <-> cryptonite" $ withMaxSuccess 10 checkScrypt
+#endif
+  , testGolden
   ]
   where
     hash8Rounds = hashPasswordWithParams testsParams8Rounds
@@ -32,6 +42,9 @@
     hash4Rounds = hashPasswordWithParams testsParams4Rounds
     testsParams4Rounds = defaultParams{ scryptRounds = 4, scryptSalt = 16 }
 
+#ifdef x86_64_HOST_ARCH
+-- The scrypt library is only available on x86_64, so we only compare password's
+-- scrypt functionality against the actual scrypt library when building on x86_64.
 checkScrypt :: Text -> Property
 checkScrypt pass = ioProperty $ do
   s@(Scrypt.Salt salt) <- Scrypt.newSalt
@@ -41,3 +54,18 @@
       PasswordHash ourHash =
         hashPasswordWithSalt defaultParams{ scryptRounds = 8 } (Salt salt) $ mkPassword pass
   return $ scryptHash === encodeUtf8 ourHash
+#endif
+
+testGolden :: TestTree
+testGolden = testGroup "Golden tests"
+    [ go "defaultParams" "Scrypt_defaultParams" defaultParams "somesalt42"
+    , go "rounds = 8" "Scrypt_rounds8" defaultParams{scryptRounds = 8} "somesalt42"
+    , go "output length = 16" "Scrypt_outputLength16" defaultParams{scryptOutputLength = 16} "somesalt42"
+    , go "scrypt length = 16" "Scrypt_saltLength16" defaultParams{scryptSalt = 16} "somesalt42"
+    , go "Other salt" "Scrypt_otherSalt" defaultParams "somesalt0"
+    ]
+  where go testName fileName params salt =
+          goldenVsString
+            testName
+            ("test/golden/" <> fileName <> ".golden")
+            (return $ fromStrict $ encodeUtf8 $ unPasswordHash $ hashPasswordWithSalt params (Salt salt) $ mkPassword "password")
