diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,15 @@
 # hoauth2 Changelog
 
+## 2.15.2 (2026-08-10)
+
+- Dependency changes
+  - Relax `crypton` upper bound to support `crypton-1.1.x` for Stackage/Hackage builds.
+  - Replace `memory` with `ram`.
+
 ## 2.15.1 (2026-04-17)
+
 - Dependency changes
   - Relax the `containers` upper bound to `< 0.9` so `containers-0.8` is supported.
-  - No API or behavior changes.
 
 ## 2.15.0 (2025-10-05)
 - Breaking changes
diff --git a/hoauth2.cabal b/hoauth2.cabal
--- a/hoauth2.cabal
+++ b/hoauth2.cabal
@@ -2,7 +2,7 @@
 name:               hoauth2
 
 -- http://wiki.haskell.org/Package_versioning_policy
-version:            2.15.1
+version:            2.15.2
 synopsis:           Haskell OAuth2 authentication client
 description:
   This package provides Haskell bindings for the OAuth2 Authorization Framework and Bearer Token Usage.
@@ -33,16 +33,14 @@
   autogen-modules:    Paths_hoauth2
   other-modules:
     Network.HTTP.Client.Contrib
-    Network.OAuth2.Internal
     Network.OAuth2.Experiment.Grants
     Network.OAuth2.Experiment.Utils
+    Network.OAuth2.Internal
     Paths_hoauth2
 
   exposed-modules:
     Network.OAuth2
     Network.OAuth2.AuthorizationRequest
-    Network.OAuth2.HttpClient
-    Network.OAuth2.TokenRequest
     Network.OAuth2.Experiment
     Network.OAuth2.Experiment.Flows
     Network.OAuth2.Experiment.Flows.AuthorizationRequest
@@ -57,6 +55,8 @@
     Network.OAuth2.Experiment.Grants.ResourceOwnerPassword
     Network.OAuth2.Experiment.Pkce
     Network.OAuth2.Experiment.Types
+    Network.OAuth2.HttpClient
+    Network.OAuth2.TokenRequest
 
   default-extensions:
     DeriveGeneric
@@ -69,23 +69,23 @@
     TypeFamilies
 
   build-depends:
-    , aeson                 >=2.0    && <2.3
-    , base                  >=4.11   && <5
-    , base64                >=1.0    && <1.1
-    , binary                >=0.8    && <0.11
-    , binary-instances      >=1.0    && <1.1
-    , bytestring            >=0.9    && <0.13
-    , containers            >=0.6    && <0.9
-    , crypton               >=0.32   && <1.1
+    , aeson                 >=2.0   && <2.3
+    , base                  >=4.11  && <5
+    , base64                >=1.0   && <1.1
+    , binary                >=0.8   && <0.11
+    , binary-instances      >=1.0   && <1.1
+    , bytestring            >=0.9   && <0.13
+    , containers            >=0.6   && <0.9
+    , crypton               >=0.32  && <1.2
     , data-default          ^>=0.8
-    , exceptions            >=0.8.3  && <0.11
-    , http-conduit          >=2.1    && <2.4
-    , http-types            >=0.11   && <0.13
-    , memory                ^>=0.18
-    , microlens             >=0.4 && <0.6
-    , text                  >=2.0    && <2.3
-    , transformers          >=0.4    && <0.7
-    , uri-bytestring        >=0.4    && <0.5
+    , exceptions            >=0.8.3 && <0.11
+    , http-conduit          >=2.1   && <2.4
+    , http-types            >=0.11  && <0.13
+    , microlens             >=0.4   && <0.6
+    , ram                   >=0.22  && <0.23
+    , text                  >=2.0   && <2.3
+    , transformers          >=0.4   && <0.7
+    , uri-bytestring        >=0.4   && <0.5
     , uri-bytestring-aeson  ^>=0.1
 
   ghc-options:
@@ -103,8 +103,8 @@
     , binary          >=0.8  && <0.11
     , hoauth2
     , hspec           >=2    && <3
+    , http-conduit    >=2.1  && <2.4
     , uri-bytestring  >=0.4  && <0.5
-    , http-conduit          >=2.1    && <2.4
 
   other-modules:
     Network.OAuth2.InternalSpec
diff --git a/src/Network/OAuth2/Experiment/Pkce.hs b/src/Network/OAuth2/Experiment/Pkce.hs
--- a/src/Network/OAuth2/Experiment/Pkce.hs
+++ b/src/Network/OAuth2/Experiment/Pkce.hs
@@ -43,7 +43,7 @@
       }
 
 encodeCodeVerifier :: BS.ByteString -> Text
-encodeCodeVerifier = B64.extractBase64 . B64.encodeBase64Unpadded . BS.pack . ByteArray.unpack . hashSHA256
+encodeCodeVerifier = B64.extractBase64 . B64.encodeBase64Unpadded . hashSHA256
 
 genCodeVerifier :: MonadIO m => m BS.ByteString
 genCodeVerifier = liftIO $ getBytesInternal BS.empty
@@ -64,8 +64,9 @@
       let bsUnreserved = ba `BS.append` BS.filter isUnreversed bs
       getBytesInternal bsUnreserved
 
-hashSHA256 :: BS.ByteString -> H.Digest H.SHA256
-hashSHA256 = H.hash
+hashSHA256 :: BS.ByteString -> BS.ByteString
+hashSHA256 bs =
+  ByteArray.convert (H.hash bs :: H.Digest H.SHA256)
 
 isUnreversed :: Word8 -> Bool
 isUnreversed w = w `BS.elem` unreverseBS
