diff --git a/RSA.cabal b/RSA.cabal
--- a/RSA.cabal
+++ b/RSA.cabal
@@ -1,6 +1,6 @@
 name:       RSA
 category:   Cryptography, Codec
-version:    2.1.0.3
+version:    2.4.1
 license:    BSD3
 license-file: LICENSE
 author:     Adam Wick <awick@galois.com>
@@ -24,8 +24,9 @@
                    bytestring          >  0.8     && < 0.12,
                    crypto-api          >= 0.10    && < 0.14,
                    crypto-pubkey-types >= 0.2     && < 0.6,
-                   pureMD5             >= 2.1     && < 2.3,
                    SHA                 >= 1.6.4.1 && < 2.0
+  if impl(ghc < 8.0)
+    build-depends: cipher-aes128       < 0.7.0.4
   exposed-modules: Codec.Crypto.RSA,
                    Codec.Crypto.RSA.Exceptions,
                    Codec.Crypto.RSA.Pure
@@ -36,13 +37,12 @@
   type:           exitcode-stdio-1.0
   Main-Is:        Test.hs
   hs-source-dirs: src,.
+  other-modules:  Codec.Crypto.RSA.Pure
   build-depends:  base                       >= 4.6     && < 7.0,
                   binary                     >  0.7     && < 1.0,
                   bytestring                 >  0.8     && < 0.12,
                   crypto-api                 >= 0.10    && < 0.14,
                   crypto-pubkey-types        >= 0.4     && < 0.6,
-                  DRBG                       >= 0.5.2   && < 0.7,
-                  pureMD5                    >= 2.1     && < 2.3,
                   QuickCheck                 >= 2.5     && < 3,
                   tagged                     >= 0.2     && < 0.9,
                   test-framework             >= 0.8.0.3 && < 0.10,
diff --git a/Test.hs b/Test.hs
--- a/Test.hs
+++ b/Test.hs
@@ -1,15 +1,12 @@
 import Codec.Crypto.RSA.Pure
 import Control.Monad
 import Data.Binary
-import qualified Data.ByteString as BSS
 import Data.ByteString.Lazy(ByteString)
 import qualified Data.ByteString.Lazy as BS
-import qualified Data.Digest.Pure.MD5 as MD5
 import Data.Digest.Pure.SHA
 import System.IO
 import Test.QuickCheck
 import Crypto.Random
-import Crypto.Random.DRBG
 
 import Test.Framework (defaultMain, testGroup)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
@@ -26,7 +23,7 @@
 main = do
   putStr   "Generating testing keys ... "
   hFlush   stdout
-  g :: GenAutoReseed HashDRBG HashDRBG <- newGenIO
+  g :: SystemRandom <- newGenIO
   let (keys, g') = buildRandomKeyPairs g (cycle keySizes) numRandomKeyPairs
   unless (all ((> 5) . public_n . fst) keys) $ fail "Something odd."
   putStrLn "done!"
@@ -38,7 +35,7 @@
     , testGroup "Testing basic helper functions" [
         testProperty "ByteString chunking works"    prop_chunkifyWorks
       , testProperty "Modular exponentiation works" prop_modExpWorks
-      , testProperty "Modular inversion works"      prop_modInvWorks
+      , testProperty "Modular inversion works"      (prop_modInvWorks g')
       ]
     , testGroup "Testing RSA core functions" [
         testProperty "Can roundtrip from Integer to BS and back" prop_i2o2iIdent
@@ -81,7 +78,6 @@
 
 instance Show HashInfo where
   show (HashInfo ident _)
-    | ident == algorithmIdent hashMD5    = "<MD5>"
     | ident == algorithmIdent hashSHA1   = "<SHA1>"
     | ident == algorithmIdent hashSHA224 = "<SHA224>"
     | ident == algorithmIdent hashSHA256 = "<SHA256>"
@@ -90,19 +86,9 @@
     | otherwise                          = "<unknownHASH>"
 
 instance Arbitrary HashInfo where
-  arbitrary = elements [hashMD5, hashSHA1, hashSHA224,
+  arbitrary = elements [hashSHA1, hashSHA224,
                        hashSHA256, hashSHA384, hashSHA512]
 
-newtype LargePrime = LP Integer
-  deriving (Show)
-
-instance Arbitrary LargePrime where
-  arbitrary =
-    do Right (g :: HashDRBG) <- (newGen . BSS.pack) `fmap` replicateM 4096 arbitrary
-       case largeRandomPrime g 64 of
-         Left _ -> fail "Large prime generation failure."
-         Right (i, _) -> return (LP i)
-
 data KeyPairIdx = KPI Int
  deriving (Show)
 
@@ -115,8 +101,7 @@
   show (HF s _) = "<" ++ s ++ ">"
 
 instance Arbitrary HashFun where
-  arbitrary = elements [HF "MD5" (encode . MD5.md5),
-                        HF "SHA1" (bytestringDigest . sha1),
+  arbitrary = elements [HF "SHA1" (bytestringDigest . sha1),
                         HF "SHA256" (bytestringDigest . sha256),
                         HF "SHA384" (bytestringDigest . sha384),
                         HF "SHA512" (bytestringDigest . sha512)]
@@ -149,12 +134,22 @@
   e' = getPositive e
   m' = getPositive m
 
-prop_modInvWorks :: LargePrime -> LargePrime -> Bool
-prop_modInvWorks (LP p) (LP q) = (e * d) `mod` phi == 1
- where 
-  e   = 65537
-  phi = (p - 1) * (q - 1)
-  d   = modular_inverse e phi
+prop_modInvWorks :: CryptoRandomGen g => g -> Word16 -> Bool
+prop_modInvWorks g0 x =
+  let (p, g1) = primeGen (x `mod` 512) g0
+      (q, _)  = primeGen (x `mod` 512) g1
+      e       = 65537
+      phi     = (p - 1) * (q - 1)
+      d       = modular_inverse e phi
+  in (e * d) `mod` phi == 1
+ where
+  primeGen pre g =
+    case randomBS g (fromIntegral pre) of
+      Left e -> error ("Error prefetching bytestring:" ++ show e)
+      Right (_, g') ->
+        case largeRandomPrime g' 64 of
+          Left  _   -> error "Large prime generation failure."
+          Right res -> res
 
 prop_i2o2iIdent :: Positive Integer -> Bool
 prop_i2o2iIdent px =
diff --git a/src/Codec/Crypto/RSA/Exceptions.hs b/src/Codec/Crypto/RSA/Exceptions.hs
--- a/src/Codec/Crypto/RSA/Exceptions.hs
+++ b/src/Codec/Crypto/RSA/Exceptions.hs
@@ -27,7 +27,7 @@
        , rsassa_pkcs1_v1_5_sign
        , rsassa_pkcs1_v1_5_verify
        -- * Hashing algorithm declarations for use in RSA functions
-       , hashMD5, hashSHA1
+       , hashSHA1
        , hashSHA224, hashSHA256, hashSHA384, hashSHA512
        -- * Other mathematical functions that are handy for implementing
        -- other RSA primitives.
@@ -259,7 +259,7 @@
 -- or 35.
 --
 -- Thus,
---   * for MD5, SHA1, and SHA256, use 512+ bit keys
+--   * for SHA1 and SHA256, use 512+ bit keys
 --   * for SHA384 and SHA512, use 1024+ bit keys
 --
 rsassa_pkcs1_v1_5_sign :: HashInfo {- ^The hash function to use -} ->
@@ -358,9 +358,6 @@
 modular_inverse = Pure.modular_inverse
 
 -- ----------------------------------------------------------------------------
-
-hashMD5 :: HashInfo
-hashMD5 = Pure.hashMD5
 
 hashSHA1 :: HashInfo
 hashSHA1 = Pure.hashSHA1
diff --git a/src/Codec/Crypto/RSA/Pure.hs b/src/Codec/Crypto/RSA/Pure.hs
--- a/src/Codec/Crypto/RSA/Pure.hs
+++ b/src/Codec/Crypto/RSA/Pure.hs
@@ -29,7 +29,7 @@
        , rsassa_pkcs1_v1_5_sign
        , rsassa_pkcs1_v1_5_verify
        -- * Hashing algorithm declarations for use in RSA functions
-       , hashMD5, hashSHA1
+       , hashSHA1
        , hashSHA224, hashSHA256, hashSHA384, hashSHA512
        -- * Other mathematical functions that are handy for implementing
        -- other RSA primitives.
@@ -56,7 +56,6 @@
 import Data.Bits
 import Data.ByteString.Lazy(ByteString)
 import qualified Data.ByteString.Lazy as BS
-import qualified Data.Digest.Pure.MD5 as MD5
 import Data.Digest.Pure.SHA
 import Data.Int
 import Data.Typeable
@@ -73,7 +72,7 @@
               | RSAIncorrectMsgSize
               | RSADecryptionError
               | RSAGenError GenError
- deriving (Show, Typeable)
+ deriving (Eq, Show, Typeable)
 
 instance Exception RSAError
 
@@ -113,7 +112,7 @@
               return (PrivateKey pub d 0 0 0 0 0)
 
 failOnError :: (Monad m, Show a) => Either a b -> m b
-failOnError (Left e)  = fail (show e)
+failOnError (Left e)  = error (show e)
 failOnError (Right b) = return b
 
 -- ----------------------------------------------------------------------------
@@ -325,7 +324,7 @@
 -- generate an error, represented by the Left constructor.
 --
 -- Futher, k (the length of the ciphertext in bytes) must be greater than or
--- equal to (2 * hLen + 2), where hLen is the length of the output of the 
+-- equal to (2 * hLen + 2), where hLen is the length of the output of the
 -- hash function in bytes. If this equation does not hold, a (different)
 -- error will be generated.
 --
@@ -345,7 +344,7 @@
          keySize    = private_size k
      -- WARNING: Step 1a is missing!
      unless (BS.length c == fromIntegral keySize) $                -- Step 1b
-       Left RSADecryptionError 
+       Left RSADecryptionError
      unless (fromIntegral keySize >= ((2 * hashLength) + 2)) $     -- Step 1c
        Left RSADecryptionError
      let c_ip = os2ip c                                            -- Step 2a
@@ -417,7 +416,7 @@
      em   <- i2osp m_i (private_size k)                         -- Step 2c
      let (zt, ps_z_m) = BS.splitAt 2 em                         -- Step 3...
          (ps, z_m)    = BS.span (/= 0) ps_z_m
-         (z, m)       = BS.splitAt 1 z_m 
+         (z, m)       = BS.splitAt 1 z_m
      when (BS.unpack zt /= [0,2]) $ Left RSADecryptionError
      when (BS.unpack z  /= [0])   $ Left RSADecryptionError
      when (BS.length ps <  8 )    $ Left RSADecryptionError
@@ -449,7 +448,7 @@
 -- or 35.
 --
 -- Thus,
---   * for MD5, SHA1, and SHA256, use 512+ bit keys
+--   * for SHA1 and SHA256, use 512+ bit keys
 --   * for SHA384 and SHA512, use 1024+ bit keys
 --
 rsassa_pkcs1_v1_5_sign :: HashInfo {- ^The hash function to use -} ->
@@ -483,17 +482,17 @@
 -- ----------------------------------------------------------------------------
 
 -- |A 'mask generation function'. The input is a bytestring, and the output
--- is a hash of the given length. Unless you know what you're doing, you 
+-- is a hash of the given length. Unless you know what you're doing, you
 -- should probably use a MGF1 formulation created with generate_MGF1.
 type MGF = ByteString -> Int64 -> Either RSAError ByteString
 
--- |Generate a mask generation function for the rsaes_oaep_*. As 
+-- |Generate a mask generation function for the rsaes_oaep_*. As
 -- suggested by the name, the generated function is an instance of the MGF1
--- function. The arguments are the underlying hash function to use and the 
+-- function. The arguments are the underlying hash function to use and the
 -- size of a hash in bytes.
 --
 -- The bytestring passed to the generated function cannot be longer than
--- 2^32 * hLen, where hLen is the passed length of the hash. 
+-- 2^32 * hLen, where hLen is the passed length of the hash.
 generateMGF1 :: (ByteString -> ByteString) -> MGF
 generateMGF1 hash mgfSeed maskLen
   | BS.length mgfSeed > ((2 ^ (32::Integer)) * hLen) = Left RSAMaskTooLong
@@ -573,7 +572,7 @@
               in if r /= 0 then (q + 1) else q
 
 -- Generate p and q. This is not necessarily the best way to do this, but it
--- appears to work. 
+-- appears to work.
 generatePQ :: CryptoRandomGen g =>
               g ->
               Int ->
@@ -677,7 +676,7 @@
   | n == 1    = Right (False, g)
   | n == 2    = Right (True, g)
   | n == 3    = Right (True, g)
-  | otherwise = 
+  | otherwise =
      -- write (n-1) as 2^s*d with d odd by factoring powers of 2 from n-1
      let (s, d) = oddify 0 (n - 1)
      in checkLoop g s d k
@@ -747,13 +746,6 @@
            in (g, x - ((b `div` a) * y), y)
 
 -- ----------------------------------------------------------------------------
-
-hashMD5 :: HashInfo
-hashMD5 = HashInfo {
-   algorithmIdent = BS.pack [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
-                             0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]
- , hashFunction   = encode . MD5.md5
- }
 
 hashSHA1 :: HashInfo
 hashSHA1 = HashInfo {
