diff --git a/hopenssl.cabal b/hopenssl.cabal
--- a/hopenssl.cabal
+++ b/hopenssl.cabal
@@ -1,5 +1,5 @@
 name:                   hopenssl
-version:                2
+version:                2.1
 copyright:              (c) 2004-2017 Peter Simons
 license:                BSD3
 license-file:           LICENSE
@@ -22,7 +22,7 @@
   location:             git://github.com/peti/hopenssl.git
 
 library
-  build-depends:        base >= 3 && < 5, bytestring
+  build-depends:        base >= 4.6 && < 5, bytestring
   hs-source-dirs:       src
   other-extensions:     ForeignFunctionInterface, EmptyDataDecls, DeriveDataTypeable,
                         FlexibleInstances, TypeSynonymInstances
diff --git a/src/OpenSSL/Digest.hs b/src/OpenSSL/Digest.hs
--- a/src/OpenSSL/Digest.hs
+++ b/src/OpenSSL/Digest.hs
@@ -122,7 +122,7 @@
 digest :: Digestable a => DigestDescription -> a -> MessageDigest
 digest algo input =
   IO.unsafePerformIO $
-    bracket createContext destroyContext $ \ctx -> do
+    bracket newContext freeContext $ \ctx -> do
       initDigest algo ctx
       updateChunk ctx input
       let mdSize = fromIntegral (_digestSize (getDigestDescription algo))
diff --git a/src/OpenSSL/EVP/Digest.hsc b/src/OpenSSL/EVP/Digest.hsc
--- a/src/OpenSSL/EVP/Digest.hsc
+++ b/src/OpenSSL/EVP/Digest.hsc
@@ -31,6 +31,7 @@
 import Numeric ( showHex )
 import System.IO.Unsafe as IO
 
+#include "openssl/opensslv.h"
 #include "openssl/evp.h"
 
 #if __GLASGOW_HASKELL__ < 800
@@ -39,6 +40,7 @@
 
 -- * Low-level API
 
+#if OPENSSL_VERSION_NUMBER < 0x1010000f
 -------------------------------------------------------------------------------
 -- ** OpenSSL Library Initialization
 -------------------------------------------------------------------------------
@@ -50,6 +52,7 @@
 -- 'digestByName'' and 'digestByName' don't have to worry about this.
 
 foreign import ccall unsafe "openssl/evp.h OpenSSL_add_all_digests" _addAllDigests :: IO ()
+#endif
 
 -------------------------------------------------------------------------------
 -- ** Accessing the Supported Digest Types
@@ -57,8 +60,10 @@
 
 data OpaqueDigestDescription
 
--- | Look up a 'Digest' by name. Be sure to call '_addAllDigests' before you
--- use this function.
+-- | Look up a 'Digest' by name.
+#if OPENSSL_VERSION_NUMBER < 0x1010000f
+-- Be sure to call '_addAllDigests' before you use this function.
+#endif
 
 foreign import ccall unsafe "openssl/evp.h EVP_get_digestbyname" _digestByName :: CString -> Ptr OpaqueDigestDescription
 
@@ -88,51 +93,49 @@
 -------------------------------------------------------------------------------
 
 -- | A context in which -- when initialized -- digest computations can be run.
--- There is a 'Storable' solely for the benefit of being able to create that
--- type with 'alloca' and '_init' instead of having to use '_create', which
--- uses the heap. Anyway, that instance does not define 'peek' nor 'poke' since
--- those make no sense.
+-- Use '_newContext' and '_freeContext' to allocate/deallocate this type.
 
 data OpaqueDigestContext
 
-instance Storable OpaqueDigestContext where
-   sizeOf _    = #{size EVP_MD_CTX}
-   alignment _ = #{alignment EVP_MD_CTX}
-   peek _      = error "Don't do this. OpaqueDigestContext is, like, opaque."
-   poke _ _    = error "Don't do this. OpaqueDigestContext is, like, opaque."
-
--- | Allocate an (initialized) 'OpaqueDigestContext' for use in a digest
+-- | Allocate and initialize an 'OpaqueDigestContext' for use in a digest
 -- computation on the heap. Release its underlying memory after use with
--- '_destroy'.
-
-foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_create" _createContext :: IO (Ptr OpaqueDigestContext)
-
--- | Initialize an 'OpaqueDigestContext' for use in a digest computation. The
--- type can be allocated on the stack with 'alloca' or on the heap with
--- '_create'.
+-- '_freeContext'.
 
-foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_init" _initContext :: Ptr OpaqueDigestContext -> IO ()
+foreign import ccall unsafe
+#if OPENSSL_VERSION_NUMBER < 0x1010000f
+  "openssl/evp.h EVP_MD_CTX_create"
+#else
+  "openssl/evp.h EVP_MD_CTX_new"
+#endif
+  _newContext :: IO (Ptr OpaqueDigestContext)
 
--- | Release all resources associated with a digest computation's context, but
--- don't release the underlying digest context structure. This allows the context
--- to be re-initiaized for use another computation.
+#if OPENSSL_VERSION_NUMBER >= 0x1010000f
+-- | Re-initialize a previously created 'OpaqueDigestContext' for use in a new
+-- digest computation.
 
-foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_cleanup" _cleanupContext :: Ptr OpaqueDigestContext -> IO CInt
+foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_reset" _resetContext :: Ptr OpaqueDigestContext -> IO ()
+#endif
 
--- | Release all resources associated with a digest computation's context and the
--- context structure itself. Use this only for context's acquired with '_create'.
+-- | Release all resources associated with a digest computation's context and
+-- the context structure itself. Use this only for context's acquired with
+-- '_newContext'.
 
-foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_destroy" _destroyContext :: Ptr OpaqueDigestContext -> IO ()
+foreign import ccall unsafe
+#if OPENSSL_VERSION_NUMBER < 0x1010000f
+  "openssl/evp.h EVP_MD_CTX_destroy"
+#else
+  "openssl/evp.h EVP_MD_CTX_free"
+#endif
+  _freeContext :: Ptr OpaqueDigestContext -> IO ()
 
 -------------------------------------------------------------------------------
 -- ** State of a Digest Computation
 -------------------------------------------------------------------------------
 
--- | Configure the given /initialized/ digest context to use the given message
--- digest algorithm. The third parameter allows developers to choose a specific
--- engine for that digest, too, but these bindings don't support choosing any
--- specific engine, so pass 'nullPtr' here to the default choice determined by
--- OpenSSL.
+-- | Configure the given digest context to use the given message digest
+-- algorithm. The third parameter allows developers to choose a specific engine
+-- for that digest, too, but these bindings don't support choosing any specific
+-- engine, so pass 'nullPtr' here to the default choice determined by OpenSSL.
 
 foreign import ccall unsafe "openssl/evp.h EVP_DigestInit_ex" _initDigest :: Ptr OpaqueDigestContext -> Ptr OpaqueDigestDescription -> Ptr OpaqueDigestEngine -> IO CInt
 
@@ -147,10 +150,10 @@
 -- to contain the digest. '_digestSize' or 'maxDigestSize' are your friends. If
 -- the 'CUInt' pointer is not 'nullPtr', then the actual size of the generated
 -- digest is written into that integer. This function does /not/ clean up the
--- digest context; this has to be done with an explicit call to
--- '_cleanupContext' or '_destroyContext'. However, it does invalidate the
--- digest state so that no further calls of '_digestUpdate' can be made without
--- re-initializing the state with '_initDigest' first.
+-- digest context; this has to be done with an explicit call to '_freeContext'.
+-- However, it does invalidate the digest state so that no further calls of
+-- '_digestUpdate' can be made without re-initializing the state with
+-- '_resetDigest' first.
 
 foreign import ccall unsafe "openssl/evp.h EVP_DigestFinal_ex" _finalizeDigest :: Ptr OpaqueDigestContext -> Ptr Word8 -> Ptr CUInt -> IO CInt
 
@@ -169,8 +172,10 @@
 digestByName' :: String -> Maybe DigestDescription
 digestByName' algo = if ptr == nullPtr then Nothing else Just (DigestDescription ptr)
   where ptr = IO.unsafePerformIO $ withCString algo $ \name -> do
+#if OPENSSL_VERSION_NUMBER < 0x1010000f
                 modifyMVar_ isDigestEngineInitialized $ \isInitialized ->
                   unless isInitialized _addAllDigests >> return True
+#endif
                 return (_digestByName name)
 
 newtype DigestContext = DigestContext { getDigestContext :: Ptr OpaqueDigestContext }
@@ -180,12 +185,14 @@
   | ptr == nullPtr = throw AttemptToConstructDigestContextFromNullPointer
   | otherwise      = DigestContext ptr
 
-initContext :: DigestContext -> IO ()
-initContext (DigestContext ctx) = _initContext ctx
+#if OPENSSL_VERSION_NUMBER >= 0x1010000f
+resetContext :: DigestContext -> IO ()
+resetContext (DigestContext ctx) = _resetContext ctx
+#endif
 
-createContext :: IO DigestContext
-createContext =
-  fmap DigestContext (throwIfNull "OpenSSL.EVP.Digest.createContext failed" _createContext)
+newContext :: IO DigestContext
+newContext =
+  fmap DigestContext (throwIfNull "OpenSSL.EVP.Digest.newContext failed" _newContext)
 
 -- | Simplified variant of '_initDigest' that (a) always chooses the default
 -- digest engine and (b) reports failure by means of an exception.
@@ -194,12 +201,8 @@
 initDigest (DigestDescription algo) (DigestContext ctx) =
   throwIfZero "OpenSSL.EVP.Digest.initDigest" (_initDigest ctx algo nullPtr)
 
-cleanupContext :: DigestContext -> IO ()
-cleanupContext (DigestContext ctx) =
-  throwIfZero "OpenSSL.EVP.Digest.cleanupContext" (_cleanupContext ctx)
-
-destroyContext :: DigestContext -> IO ()
-destroyContext (DigestContext ctx) = _destroyContext ctx
+freeContext :: DigestContext -> IO ()
+freeContext (DigestContext ctx) = _freeContext ctx
 
 updateDigest :: DigestContext -> Ptr a -> CSize -> IO ()
 updateDigest (DigestContext ctx) ptr len =
diff --git a/test/CheckLowLevelDigestAPI.hs b/test/CheckLowLevelDigestAPI.hs
--- a/test/CheckLowLevelDigestAPI.hs
+++ b/test/CheckLowLevelDigestAPI.hs
@@ -23,12 +23,10 @@
 digest :: DigestDescription -> String -> IO String
 digest algo input = do
   let digestSize = _digestSize (getDigestDescription algo)
-  md <- alloca $ \ctx' -> do
-    let ctx = digestContext ctx'
-    bracket_ (initContext ctx) (cleanupContext ctx) $ do
-      initDigest algo ctx
-      withCStringLen input $ \(ptr,len) -> updateDigest ctx ptr (fromIntegral len)
-      allocaArray (fromIntegral digestSize) $ \md -> do
-        finalizeDigest ctx md
-        peekArray (fromIntegral digestSize) md
+  md <- bracket newContext freeContext $ \ctx -> do
+    initDigest algo ctx
+    withCStringLen input $ \(ptr,len) -> updateDigest ctx ptr (fromIntegral len)
+    allocaArray (fromIntegral digestSize) $ \md -> do
+      finalizeDigest ctx md
+      peekArray (fromIntegral digestSize) md
   return (md >>= toHex)
