diff --git a/src/Tahoe/SDMF.hs b/src/Tahoe/SDMF.hs
index 0aaf41a1fa7e30ed6db779c836e1ce9da6a510fa..b398639b237c260f58d3faf046d8455bd138a00a 100644
--- a/src/Tahoe/SDMF.hs
+++ b/src/Tahoe/SDMF.hs
@@ -1,4 +1,8 @@
 -- | Expose the library's public interface.
-module Tahoe.SDMF (Share (..)) where
+module Tahoe.SDMF (
+    module Tahoe.SDMF.Internal.Share,
+    module Tahoe.SDMF.Internal.Capability,
+) where
 
-import Tahoe.SDMF.Internal.Share
+import Tahoe.SDMF.Internal.Capability (Reader (..), Writer (..))
+import Tahoe.SDMF.Internal.Share (Share (..))
diff --git a/src/Tahoe/SDMF/Internal/Capability.hs b/src/Tahoe/SDMF/Internal/Capability.hs
new file mode 100644
index 0000000000000000000000000000000000000000..56d6ed1616af9478126c40404844e279d0ee43bd
--- /dev/null
+++ b/src/Tahoe/SDMF/Internal/Capability.hs
@@ -0,0 +1,21 @@
+-- | Structured representations of SDMF capabilities.
+module Tahoe.SDMF.Internal.Capability where
+
+import Prelude hiding (Read)
+
+import qualified Data.ByteString as B
+import Tahoe.SDMF.Internal.Keys (Read, Write)
+
+-- | A read capability for an SDMF object.
+data Reader = Reader
+    { readerReadKey :: Read
+    , readerVerificationKeyHash :: B.ByteString
+    }
+    deriving (Show)
+
+-- | A write capability for an SDMF object.
+data Writer = Writer
+    { writerWriteKey :: Write
+    , writerReader :: Reader
+    }
+    deriving (Show)
diff --git a/src/Tahoe/SDMF/Internal/Keys.hs b/src/Tahoe/SDMF/Internal/Keys.hs
index e40d6fbefa909e638a689f7d802a3b7ee53bc1d4..29f38c6881086c25ab7b3467edd48298d9d77525 100644
--- a/src/Tahoe/SDMF/Internal/Keys.hs
+++ b/src/Tahoe/SDMF/Internal/Keys.hs
@@ -34,10 +34,15 @@ newtype Signature = Signature {unSignature :: RSA.PrivateKey}
     deriving newtype (Eq, Show)
 
 data Write = Write {unWrite :: AES128, writeKeyBytes :: ByteArray.ScrubbedBytes}
+
 instance Show Write where
     show (Write _ bs) = T.unpack $ T.concat ["<WriteKey ", encodeBase32Unpadded (ByteArray.convert bs), ">"]
 
 data Read = Read {unRead :: AES128, readKeyBytes :: ByteArray.ScrubbedBytes}
+
+instance Show Read where
+    show (Read _ bs) = T.unpack $ T.concat ["<ReadKey ", encodeBase32Unpadded (ByteArray.convert bs), ">"]
+
 newtype StorageIndex = StorageIndex {unStorageIndex :: B.ByteString}
 
 newtype WriteEnablerMaster = WriteEnablerMaster ByteArray.ScrubbedBytes
diff --git a/tahoe-ssk.cabal b/tahoe-ssk.cabal
index d7e3e7b2fa120ba97e87eda4899e187d4bda37ad..a87dac7d758781bcd3043fb7a3b8c145f3d41513 100644
--- a/tahoe-ssk.cabal
+++ b/tahoe-ssk.cabal
@@ -64,6 +64,7 @@ library
   hs-source-dirs:     src
   exposed-modules:
     Tahoe.SDMF
+    Tahoe.SDMF.Internal.Capability
     Tahoe.SDMF.Internal.Keys
     Tahoe.SDMF.Internal.Share
     Tahoe.SDMF.Keys