diff --git a/flake.lock b/flake.lock
index 17b6fae41c1253ed5ed7f7d73569158bcc7b662f..c1bfd53e597a3399cb277becd185b8bc57d653bb 100644
--- a/flake.lock
+++ b/flake.lock
@@ -516,16 +516,16 @@
         ]
       },
       "locked": {
-        "lastModified": 1683552888,
-        "narHash": "sha256-h9pgP/LYPtUr5CeCAhqt1XJyAqKTnkQxuIygiTulU/U=",
-        "ref": "refs/tags/0.1.0.1",
-        "rev": "05aeb5a433b85406ca3c0c313c46299a1026ade0",
-        "revCount": 344,
+        "lastModified": 1696262854,
+        "narHash": "sha256-0/6VEsjXe7EvYY2BnkWkmHCVzdp1WcFLjx5mvHDMLnM=",
+        "ref": "refs/tags/0.2.0.0",
+        "rev": "42ae52257ec6e6d8eaa9a56662ca5edfbce8074b",
+        "revCount": 487,
         "type": "git",
         "url": "https://whetstone.private.storage/PrivateStorage/tahoe-chk"
       },
       "original": {
-        "ref": "refs/tags/0.1.0.1",
+        "ref": "refs/tags/0.2.0.0",
         "type": "git",
         "url": "https://whetstone.private.storage/PrivateStorage/tahoe-chk"
       }
diff --git a/flake.nix b/flake.nix
index 4fe75f92082b0c4a95343044a9db510b032380b4..b52496ae27e7f1764052672cffad6a8088bedcc3 100644
--- a/flake.nix
+++ b/flake.nix
@@ -7,7 +7,7 @@
     hs-flake-utils.url = "git+https://whetstone.private.storage/jcalderone/hs-flake-utils.git?ref=main";
     nixpkgs.follows = "hs-flake-utils/nixpkgs";
     tahoe-chk = {
-      url = "git+https://whetstone.private.storage/PrivateStorage/tahoe-chk?ref=refs/tags/0.1.0.1";
+      url = "git+https://whetstone.private.storage/PrivateStorage/tahoe-chk?ref=refs/tags/0.2.0.0";
       inputs.nixpkgs.follows = "hs-flake-utils/nixpkgs";
     };
     tahoe-capabilities = {
diff --git a/src/Tahoe/SDMF/Internal/Capability.hs b/src/Tahoe/SDMF/Internal/Capability.hs
index a0a194347d4f42dd944eef0d580c5f6f9d31dd63..d8b494f6c7694267f63c0519aeefa852fcd50165 100644
--- a/src/Tahoe/SDMF/Internal/Capability.hs
+++ b/src/Tahoe/SDMF/Internal/Capability.hs
@@ -5,7 +5,7 @@ import Prelude hiding (Read)
 
 import Control.Applicative ((<|>))
 import Control.Monad (void)
-import Crypto.Hash (Digest, SHA256, digestFromByteString)
+import Crypto.Hash (digestFromByteString)
 import Data.Binary (decode)
 import qualified Data.ByteArray as ByteArray
 import qualified Data.ByteString as B
@@ -16,6 +16,7 @@ import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
 import Data.Void (Void)
 import Data.Word (Word16)
+import Tahoe.CHK.SHA256d (Digest' (Digest'), SHA256d)
 import Tahoe.Capability (ConfidentialShowable (..))
 import Tahoe.SDMF.Internal.Keys (
     Read (readKeyBytes),
@@ -49,7 +50,7 @@ instance ConfidentialShowable SDMF where
 -- | A verify capability for an SDMF object.
 data Verifier = Verifier
     { verifierStorageIndex :: StorageIndex
-    , verifierVerificationKeyHash :: Digest SHA256
+    , verifierVerificationKeyHash :: Digest' SHA256d
     }
     deriving (Eq, Show)
 
@@ -86,14 +87,14 @@ instance ConfidentialShowable Writer where
     confidentiallyShow = dangerRealShow . SDMFWriter
 
 -- | Diminish a write key to a read key and wrap it in a reader capability.
-deriveReader :: Write -> Digest SHA256 -> Maybe Reader
+deriveReader :: Write -> Digest' SHA256d -> Maybe Reader
 deriveReader w fingerprint = Reader <$> readKey <*> verifier
   where
     readKey = deriveReadKey w
     verifier = flip deriveVerifier fingerprint <$> readKey
 
 -- | Diminish a read key to a verify key and wrap it in a verifier capability.
-deriveVerifier :: Read -> Digest SHA256 -> Verifier
+deriveVerifier :: Read -> Digest' SHA256d -> Verifier
 deriveVerifier readKey = Verifier storageIndex
   where
     storageIndex = deriveStorageIndex readKey
@@ -133,7 +134,7 @@ pPieces ::
     -- | A function to convert the first bytestring to a result value.
     (B.ByteString -> a) ->
     -- | A parser for the two pieces of the SDMF capability.
-    Parser (a, Digest SHA256)
+    Parser (a, Digest' SHA256d)
 pPieces prefix convertSecret = do
     void $ string prefix
     secret <- convertSecret <$> pBase32 rfc3548Alphabet 128
@@ -142,7 +143,7 @@ pPieces prefix convertSecret = do
     case digestFromByteString digestBytes of
         Nothing -> failure Nothing mempty
         Just verificationKeyHash ->
-            pure (secret, verificationKeyHash)
+            pure (secret, Digest' verificationKeyHash)
 
 {- | A parser combinator for an arbitrary byte string of a fixed length,
  encoded using base32.
diff --git a/src/Tahoe/SDMF/Internal/Encoding.hs b/src/Tahoe/SDMF/Internal/Encoding.hs
index 5d98a76f3e959e77d88e232aee347728976062e3..f752286822be96a7f70bdcbb91e1437ef4d986c1 100644
--- a/src/Tahoe/SDMF/Internal/Encoding.hs
+++ b/src/Tahoe/SDMF/Internal/Encoding.hs
@@ -5,8 +5,8 @@
 -}
 module Tahoe.SDMF.Internal.Encoding where
 
-import Control.Monad.Fail (MonadFail)
 import Control.Monad (when)
+import Control.Monad.Fail (MonadFail)
 import Control.Monad.IO.Class (MonadIO (liftIO))
 import Crypto.Hash (digestFromByteString)
 import Crypto.Random (MonadRandom)
@@ -18,6 +18,7 @@ import qualified Data.Text as T
 import Data.Word (Word16, Word64, Word8)
 import Tahoe.CHK (padCiphertext, zfec, zunfec)
 import Tahoe.CHK.Merkle (MerkleTree (MerkleLeaf))
+import Tahoe.CHK.SHA256d (Digest' (Digest'), zero)
 import Tahoe.SDMF.Internal.Capability (Reader (..), Writer (..), deriveReader)
 import Tahoe.SDMF.Internal.Converting (from, tryInto)
 import qualified Tahoe.SDMF.Internal.Keys as Keys
@@ -91,7 +92,7 @@ makeShare shareSequenceNumber shareIV shareRequiredShares shareTotalShares share
     shareRootHash = B.replicate 32 0
     shareSignature = B.replicate 32 0 -- XXX Actually compute sig, and is it 32 bytes?
     shareHashChain = HashChain []
-    shareBlockHashTree = MerkleLeaf (B.replicate 32 0) -- XXX Real hash here, plus length check
+    shareBlockHashTree = MerkleLeaf zero -- XXX Real hash here, plus length check
 
 {- | Decode some SDMF shares to recover the original ciphertext.
 
@@ -124,7 +125,7 @@ capabilityForKeyPair keypair =
     Writer <$> writerWriteKey <*> maybeToEither' "Failed to derive read capability" writerReader
   where
     writerWriteKey = maybeToEither "Failed to derive write key" . Keys.deriveWriteKey . Keys.toSignatureKey $ keypair
-    verificationKeyHash = digestFromByteString . Keys.deriveVerificationHash . Keys.toVerificationKey $ keypair
+    verificationKeyHash = fmap Digest' . digestFromByteString . Keys.deriveVerificationHash . Keys.toVerificationKey $ keypair
     writerReader = deriveReader <$> writerWriteKey <*> maybeToEither "Failed to interpret verification hash" verificationKeyHash
 
 maybeToEither :: a -> Maybe b -> Either a b
diff --git a/src/Tahoe/SDMF/Internal/Share.hs b/src/Tahoe/SDMF/Internal/Share.hs
index 685e1f4f29f64dffa0eff18cbb58df003f975c78..dda046d4f16c303f624040aa0e99ddc2a823f377 100644
--- a/src/Tahoe/SDMF/Internal/Share.hs
+++ b/src/Tahoe/SDMF/Internal/Share.hs
@@ -17,6 +17,7 @@ import Data.Int (Int64)
 import Data.Word (Word16, Word32, Word64, Word8)
 import Data.X509 (PrivKey (PrivKeyRSA), PubKey (PubKeyRSA))
 import Tahoe.CHK.Merkle (MerkleTree, leafHashes)
+import Tahoe.CHK.SHA256d (Digest' (Digest'), SHA256d, toBytes)
 import Tahoe.SDMF.Internal.Converting (From (from), into, tryInto)
 import qualified Tahoe.SDMF.Internal.Keys as Keys
 
@@ -81,7 +82,7 @@ data Share = Share
       -- ... something about verification I dunno. XXX
       shareHashChain :: HashChain
     , -- | A merkle tree where leaves are the hashes of the blocks in this share.
-      shareBlockHashTree :: MerkleTree
+      shareBlockHashTree :: MerkleTree B.ByteString SHA256d
     , -- | The share data (erasure encoded ciphertext).
       shareData :: LB.ByteString
     , -- | The encrypted 2048 bit "signature" RSA key.
@@ -113,7 +114,7 @@ instance Binary Share where
         putByteString shareEncryptedPrivateKey
       where
         verificationKeyBytes = Keys.verificationKeyToBytes shareVerificationKey
-        blockHashTreeBytes = B.concat . leafHashes $ shareBlockHashTree
+        blockHashTreeBytes = B.concat . fmap toBytes . leafHashes $ shareBlockHashTree
 
         -- Some conversions could fail because we can't be completely sure of
         -- the size of the data we're working with.  Put has no good failure
diff --git a/tahoe-ssk.cabal b/tahoe-ssk.cabal
index 6eceb3ee18a43068ffecdfa1666efa0d1fa7475f..b0c4d8fc4086fd8b21ee60d3d62ae1540479730a 100644
--- a/tahoe-ssk.cabal
+++ b/tahoe-ssk.cabal
@@ -132,7 +132,7 @@ library
 
   -- This dependency isn't ideal.  Move common bits out to
   -- another library.
-  build-depends:   tahoe-chk >=0.1 && <0.2
+  build-depends:   tahoe-chk >=0.2 && <0.3
 
 test-suite tahoe-ssk-test
   import:
@@ -167,7 +167,7 @@ test-suite tahoe-ssk-test
     , megaparsec          >=8.0      && <9.3
     , memory              >=0.15     && <0.17
     , tahoe-capabilities  >=0.1      && <0.2
-    , tahoe-chk           >=0.1      && <0.2
+    , tahoe-chk           >=0.2      && <0.3
     , tahoe-ssk
     , tasty               >=1.2.3    && <1.5
     , tasty-hedgehog      >=1.0.0.2  && <1.2
diff --git a/test/Generators.hs b/test/Generators.hs
index 993edc5b3d9f3b3c41191be77289888a776794ec..73dea60e0c8602f8d80147927c4e3efda730a5f0 100644
--- a/test/Generators.hs
+++ b/test/Generators.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
 module Generators where
 
 import Crypto.Cipher.Types (makeIV)
@@ -10,7 +12,7 @@ import Data.Bifunctor (Bifunctor (first))
 import qualified Data.Binary as Binary
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as LB
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Data.Word (Word16)
 import Data.X509 (PrivKey (PrivKeyRSA))
 import GHC.IO.Unsafe (unsafePerformIO)
@@ -18,6 +20,7 @@ import Hedgehog (MonadGen)
 import qualified Hedgehog.Gen as Gen
 import qualified Hedgehog.Range as Range
 import Tahoe.CHK.Merkle (MerkleTree (..), makeTreePartial)
+import Tahoe.CHK.SHA256d (Digest' (Digest'), SHA256d)
 import Tahoe.SDMF (Reader (..), SDMF (..), Share (..), Verifier (..), Writer (..))
 import Tahoe.SDMF.Internal.Capability (deriveReader)
 import Tahoe.SDMF.Internal.Keys (keyLength)
@@ -87,12 +90,16 @@ rsaKeyPair bs = do
                 _ -> error "Expected RSA Private Key"
     kp
 
-merkleTrees :: MonadGen m => Range.Range Int -> m MerkleTree
-merkleTrees r = makeTreePartial <$> Gen.list r genHash
+merkleTrees :: MonadGen m => Range.Range Int -> m (MerkleTree B.ByteString SHA256d)
+merkleTrees r = makeTreePartial <$> Gen.list r digests
 
--- | Generate ByteStrings which could be sha256d digests.
-genHash :: MonadGen m => m B.ByteString
-genHash = Gen.bytes . Range.singleton . hashDigestSize $ SHA256
+-- | Generate Digest' values for some hash algorithm.  Shrinks toward "aaa..."
+digests :: forall m hash. (MonadGen m, HashAlgorithm hash) => m (Digest' hash)
+digests =
+    Digest'
+        . fromMaybe (error "Failed to interpret bytes as digest")
+        . digestFromByteString
+        <$> Gen.bytes (Range.singleton (hashDigestSize (undefined :: hash)))
 
 -- | Generate lists of two-tuples of share identifier and share root hash.
 shareHashChains :: MonadGen m => m HashChain
@@ -142,7 +149,3 @@ verifiers = readerVerifier <$> readers
 -- | Build SDMF storage indexes.
 storageIndexes :: MonadGen m => m Keys.StorageIndex
 storageIndexes = Keys.StorageIndex <$> Gen.bytes (Range.singleton keyLength)
-
--- | Build SHA256 digests.
-digests :: MonadGen m => m (Digest SHA256)
-digests = fromJust . digestFromByteString <$> Gen.bytes (Range.singleton 32)
diff --git a/test/Spec.hs b/test/Spec.hs
index 30a209f7f909b1b94e1dc1d41a35f9f144a83762..a078716b1f6c7d257dd0ff804cd12be9ababb65c 100644
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -27,6 +27,7 @@ import Generators (capabilities, encodingParameters, genRSAKeys, ivLength, share
 import qualified Hedgehog.Gen as Gen
 import qualified Hedgehog.Range as Range
 import System.IO (hSetEncoding, stderr, stdout, utf8)
+import Tahoe.CHK.SHA256d (Digest' (Digest'))
 import Tahoe.Capability (confidentiallyShow)
 import qualified Tahoe.SDMF
 import Tahoe.SDMF.Internal.Capability (deriveVerifier)
@@ -206,7 +207,7 @@ tests =
 
             let (Right writeKey) = Binary.decode . LB.fromStrict <$> decodeBase32Unpadded "vdv6pcqkblsguvkagrblr3gopu"
                 (Just readerReadKey) = Keys.deriveReadKey writeKey
-                (Just readerVerifier) = deriveVerifier readerReadKey <$> digestFromByteString ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" :: B.ByteString)
+                (Just readerVerifier) = deriveVerifier readerReadKey . Digest' <$> digestFromByteString ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" :: B.ByteString)
                 reader = Tahoe.SDMF.Reader{..}
             ciphertext <- Tahoe.SDMF.decode reader [(0, s0), (6, s6), (9, s9)]
             let (Right expectedCiphertext) = LB.fromStrict <$> decodeBase32Unpadded "6gutkha6qd4g3lxahth2dw2wjekadwoxvmazrnfq5u5j6a7quu5qy6nz3dvosx2gisdjshdtd5xphqvqjco5pq73qi"