diff --git a/README.md b/README.md
index b5fa4d9f90c5430e6279adce6344bb06ecd0dbc7..e824e77ce98dc2c4f12bae819fdd89a603c0a972 100644
--- a/README.md
+++ b/README.md
@@ -22,3 +22,72 @@ with the benefit of the experience gained from creating and maintaining the Pyth
 a number of implementation decisions can be made differently to produce a more efficient, more flexible, simpler implementation and API.
 Also,
 the Python implementation claims no public library API for users outside of the Tahoe-LAFS project itself.
+
+## Cryptographic Library Choice
+
+This library uses cryptonite for cryptography,
+motivated by the following considerations.
+
+SDMF uses
+* SHA256 for tagged hashes for key derivation and for integrity (XXX right word?) checks on some data.
+* AES128 for encryption of the signature key and the application plaintext data.
+* RSA for signatures proving write authority.
+
+There are a number of Haskell libraries that provide all of these:
+
+* Crypto
+  * Does not support the AES mode we require (CTR).
+
+* HsOpenSSL
+  * Bindings to a C library, OpenSSL, which may complicate the build process.
+  * OpenSSL's security and reliability track record also leaves something to be desired.
+
+* cryptonite
+  * Has all of the primitive cryptographic functionality we need.
+
+We want a library that:
+
+* Can be used with reflex-platform
+  * ghc 8.6.5 compatible
+* Can be cross-compiled to different targets from x86_64-linux
+  * Mainly armeabi and armv7
+* Is suitable for real-world security purposes
+  * not a demo or a toy library
+  * avoids real-world pitfalls (side-channel attacks, etc), not just textbook issues
+  * has more than a handful of other users
+
+### SHA256
+
+There are a number of Haskell libraries that provide this primitive:
+
+* Crypto
+* HsOpenSSL
+* SHA
+* cryptohash
+* cryptonite
+* dhall
+* hashing
+* nettle
+* sbv
+* tls
+
+### AES128
+
+* Crypto
+* HsOpenSSL
+* cipher-aes
+* cipher-aes128
+* crypto
+* cryptocipher
+* cryptonite
+* cryptostore
+* nettle
+
+### RSA
+
+SDMF depends on RSA for signatures proving write authority.
+
+* Crypto
+* HsOpenSSL
+* RSA
+* cryptonite
diff --git a/src/Tahoe/SDMF/Internal/Share.hs b/src/Tahoe/SDMF/Internal/Share.hs
index f4587950a072be0798d3b09a37608e1dfdaf841e..e5bad8830d3d697073ce1a1c0f4cf4f30f44b7c5 100644
--- a/src/Tahoe/SDMF/Internal/Share.hs
+++ b/src/Tahoe/SDMF/Internal/Share.hs
@@ -3,16 +3,20 @@ module Tahoe.SDMF.Internal.Share where
 
 import Control.Monad (unless)
 import Crypto.Cipher.AES (AES128)
+import Crypto.Cipher.Types (Cipher (cipherInit), IV, makeIV)
+import Crypto.Error (maybeCryptoError)
 import qualified Crypto.PubKey.RSA.Types as RSA
-import Crypto.Types (IV (IV, initializationVector))
 import Data.ASN1.BinaryEncoding (DER (DER))
 import Data.ASN1.Encoding (ASN1Encoding (encodeASN1), decodeASN1')
 import Data.ASN1.Types (ASN1Object (fromASN1, toASN1))
 import Data.Binary (Binary (..), Get, getWord8)
 import Data.Binary.Get (bytesRead, getByteString, getLazyByteString, getRemainingLazyByteString, getWord16be, getWord32be, getWord64be, isEmpty, isolate)
 import Data.Binary.Put (putByteString, putLazyByteString, putWord16be, putWord32be, putWord64be, putWord8)
+import qualified Data.ByteArray as ByteArray
 import qualified Data.ByteString as B
+import Data.ByteString.Base32 (encodeBase32Unpadded)
 import qualified Data.ByteString.Lazy as LB
+import qualified Data.Text as T
 import Data.Word (Word16, Word64, Word8)
 import Data.X509 (PubKey (PubKeyRSA))
 import Tahoe.CHK.Merkle (MerkleTree, leafHashes)
@@ -57,7 +61,7 @@ data Share = Share
     , -- | "R" (root of share hash merkle tree)
       shareRootHash :: B.ByteString
     , -- | The IV for encryption of share data.
-      shareIV :: IV AES128
+      shareIV :: SDMF_IV
     , -- | The total number of encoded shares (k).
       shareTotalShares :: Word8
     , -- | The number of shares required for decoding (N).
@@ -86,12 +90,19 @@ data Share = Share
     }
     deriving (Eq, Show)
 
+newtype SDMF_IV = SDMF_IV (IV AES128)
+    deriving (Eq)
+    deriving newtype (ByteArray.ByteArrayAccess)
+
+instance Show SDMF_IV where
+    show (SDMF_IV iv) = T.unpack . T.toLower . encodeBase32Unpadded . ByteArray.convert $ iv
+
 instance Binary Share where
     put Share{..} = do
         putWord8 0
         putWord64be shareSequenceNumber
         putByteString shareRootHash
-        putByteString . initializationVector $ shareIV
+        putByteString . ByteArray.convert $ shareIV
         putWord8 shareTotalShares
         putWord8 shareRequiredShares
         putWord64be shareSegmentSize
@@ -125,7 +136,12 @@ instance Binary Share where
         unless (version == 0) (fail $ "Only version 0 is supported; got version " <> show version)
         shareSequenceNumber <- getWord64be
         shareRootHash <- getByteString 32
-        shareIV <- IV <$> getByteString 16
+        ivBytes <- getByteString 16
+        shareIV <-
+            SDMF_IV <$> case makeIV ivBytes of
+                Nothing -> fail "Could not decode IV"
+                Just iv -> pure iv
+
         shareTotalShares <- getWord8
         shareRequiredShares <- getWord8
         shareSegmentSize <- getWord64be
diff --git a/tahoe-ssk.cabal b/tahoe-ssk.cabal
index e8e79204194a03efb6105a4378fcea6ea50ce25a..470d125134527d3a4445321daf0d2105c5e994b5 100644
--- a/tahoe-ssk.cabal
+++ b/tahoe-ssk.cabal
@@ -69,12 +69,12 @@ library
     , asn1-encoding
     , asn1-types
     , base
+    , base32
     , binary
     , bytestring
-    , crypto-api
-    , crypto-pubkey-types
     , cryptonite
-    , RSA
+    , memory
+    , text
     , x509
 
   -- This dependency isn't ideal.  Move common bits out to
@@ -119,14 +119,11 @@ test-suite tahoe-ssk-test
   build-depends:
     , asn1-encoding
     , asn1-types
-    , base                 ^>=4.14.3.0
+    , base            ^>=4.14.3.0
     , binary
     , bytestring
-    , crypto-api
-    , crypto-pubkey-types
     , cryptonite
     , hedgehog
-    , RSA
     , tahoe-chk
     , tahoe-ssk
     , tasty
@@ -145,6 +142,4 @@ executable make-keypairs
     , asn1-types
     , base
     , bytestring
-    , crypto-api
-    , crypto-pubkey-types
-    , RSA
+    , cryptonite
diff --git a/test/Generators.hs b/test/Generators.hs
index 916105480e795d564e32d12bbe54d0f7c64ded65..b43ea31047f9407fb1ef78b29c3040f191aff917 100644
--- a/test/Generators.hs
+++ b/test/Generators.hs
@@ -1,9 +1,9 @@
 module Generators where
 
+import Crypto.Cipher.Types (makeIV)
 import Crypto.Hash (HashAlgorithm (hashDigestSize))
 import Crypto.Hash.Algorithms (SHA256 (SHA256))
-import qualified Crypto.PubKey.RSA.Types as RSA
-import Crypto.Types (IV (..))
+import qualified Crypto.PubKey.RSA as RSA
 import Data.ASN1.BinaryEncoding (DER (DER))
 import Data.ASN1.Encoding (ASN1Decoding (decodeASN1), ASN1Encoding (encodeASN1))
 import Data.ASN1.Types (ASN1Object (fromASN1, toASN1))
@@ -16,8 +16,8 @@ import Hedgehog (MonadGen)
 import qualified Hedgehog.Gen as Gen
 import qualified Hedgehog.Range as Range
 import Tahoe.CHK.Merkle (MerkleTree (..), makeTreePartial)
-import Tahoe.SDMF (Share (..))
-import Tahoe.SDMF.Internal.Share (HashChain (HashChain))
+import Tahoe.SDMF (KeyPair (..), Share (..), toPublicKey)
+import Tahoe.SDMF.Internal.Share (HashChain (HashChain), SDMF_IV (SDMF_IV))
 
 rootHashLength :: Int
 rootHashLength = 32
@@ -32,22 +32,26 @@ signatureLength = Range.linear 250 260
  semantically valid.
 -}
 shares :: MonadGen m => m Share
-shares =
-    genRSAKeys >>= \keypair ->
-        Share
-            <$> Gen.word64 Range.exponentialBounded -- shareSequenceNumber
-            <*> Gen.bytes (Range.singleton rootHashLength) -- shareRootHash
-            <*> (IV <$> Gen.bytes (Range.singleton ivLength)) -- shareIV
-            <*> Gen.word8 Range.exponentialBounded -- shareTotalShares
-            <*> Gen.word8 Range.exponentialBounded -- shareRequiredShares
-            <*> Gen.word64 Range.exponentialBounded -- shareSegmentSize
-            <*> Gen.word64 Range.exponentialBounded -- shareDataLength
-            <*> pure (RSA.toPublicKey keypair) -- shareVerificationKey
-            <*> Gen.bytes signatureLength -- shareSignature
-            <*> shareHashChains -- shareHashChain
-            <*> merkleTrees (Range.singleton 1) -- shareBlockHashTree
-            <*> (LB.fromStrict <$> Gen.bytes (Range.exponential 0 1024)) -- shareData
-            <*> (pure . LB.toStrict . toDER . PrivKeyRSA . RSA.toPrivateKey) keypair -- shareEncryptedPrivateKey
+shares = do
+    keypair <- genRSAKeys
+    iv <- makeIV <$> Gen.bytes (Range.singleton ivLength)
+    case iv of
+        Nothing -> error "Could not build IV for SDMF share"
+        Just iv' ->
+            Share
+                <$> Gen.word64 Range.exponentialBounded -- shareSequenceNumber
+                <*> Gen.bytes (Range.singleton rootHashLength) -- shareRootHash
+                <*> pure (SDMF_IV iv') -- shareIV
+                <*> Gen.word8 Range.exponentialBounded -- shareTotalShares
+                <*> Gen.word8 Range.exponentialBounded -- shareRequiredShares
+                <*> Gen.word64 Range.exponentialBounded -- shareSegmentSize
+                <*> Gen.word64 Range.exponentialBounded -- shareDataLength
+                <*> pure (toPublicKey keypair) -- shareVerificationKey
+                <*> Gen.bytes signatureLength -- shareSignature
+                <*> shareHashChains -- shareHashChain
+                <*> merkleTrees (Range.singleton 1) -- shareBlockHashTree
+                <*> (LB.fromStrict <$> Gen.bytes (Range.exponential 0 1024)) -- shareData
+                <*> (pure . LB.toStrict . toDER . PrivKeyRSA . toPrivateKey) keypair -- shareEncryptedPrivateKey
   where
     toDER = encodeASN1 DER . flip toASN1 []
 
@@ -59,7 +63,7 @@ shares =
  challenging, this implementation just knows a few RSA key pairs already and
  will give back one of them.
 -}
-genRSAKeys :: MonadGen m => m RSA.KeyPair
+genRSAKeys :: MonadGen m => m KeyPair
 genRSAKeys = Gen.element (map rsaKeyPair rsaKeyPairBytes)
 
 -- I'm not sure how to do IO in MonadGen so do the IO up front unsafely (but
@@ -68,13 +72,13 @@ rsaKeyPairBytes :: [LB.ByteString]
 {-# NOINLINE rsaKeyPairBytes #-}
 rsaKeyPairBytes = unsafePerformIO $ mapM (\n -> LB.readFile ("test/data/rsa-privkey-" <> show n <> ".der")) [0 .. 4 :: Int]
 
-rsaKeyPair :: LB.ByteString -> RSA.KeyPair
+rsaKeyPair :: LB.ByteString -> KeyPair
 rsaKeyPair bs = do
     let (Right kp) = do
             asn1s <- first show (decodeASN1 DER bs)
             (r, _) <- fromASN1 asn1s
             case r of
-                PrivKeyRSA pk -> pure $ RSA.KeyPair pk
+                PrivKeyRSA pk -> pure $ KeyPair pk
                 _ -> error "Expected RSA Private Key"
     kp