diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for the hashes package
 
+## 0.2.3 -- 2022-11-22
+
+*   Support reset and reuse of context for OpenSSL digests.
+*   Avoid the use of deprecated OpenSSL methods.
+*   Add methods to write digests directly to a pointer for Keccak digests.
+
 ## 0.2.2.1 -- 2022-09-28
 
 *   Support for Apple Silicon (`aarch64_HOST_ARCH`)
diff --git a/cbits/keccak.c b/cbits/keccak.c
--- a/cbits/keccak.c
+++ b/cbits/keccak.c
@@ -34,7 +34,7 @@
 /* *************************************************************************** */
 /* OpenSSL 1.1 and OpenSSL 3.0 */
 
-/* The computation of the magic offset is base on the keccak_st structure in
+/* The computation of the magic offset is based on the keccak_st structure in
  * OpenSSL-1.1 and OpenSSL-3.0
  *
  * Assuming conventional alignment, the bytes offset is
@@ -79,7 +79,7 @@
 
 /* OPENSSL 3.1 */
 #if OPENSSL_VERSION_NUMBER >= 0x31000000L
-#define SET_PAD_BYTE 
+#define SET_PAD_BYTE
 
 /* OPENSSL 3.0 */
 #elif OPENSSL_VERSION_NUMBER >= 0x30000000L
@@ -111,7 +111,7 @@
     int ok = 1;
     const EVP_MD *md = NULL;
     CHECKED(md = EVP_get_digestbyname("SHA3-256"));
-    CHECKED(EVP_DigestInit(ctx, md));
+    CHECKED(EVP_DigestInit_ex(ctx, md, NULL));
     SET_PAD_BYTE;
 finally:
     return ok;
@@ -121,12 +121,28 @@
     int ok = 1;
     const EVP_MD *md = NULL;
     CHECKED(md = EVP_get_digestbyname("SHA3-512"));
-    CHECKED(EVP_DigestInit(ctx, md));
+    CHECKED(EVP_DigestInit_ex(ctx, md, NULL));
     SET_PAD_BYTE;
 finally:
     return ok;
 }
 
+int keccak256_reset(KECCAK512_CTX *ctx) {
+    int ok = 1;
+    CHECKED(EVP_DigestInit_ex(ctx, NULL, NULL));
+    SET_PAD_BYTE;
+finally:
+    return ok;
+}
+
+int keccak512_reset(KECCAK512_CTX *ctx) {
+    int ok = 1;
+    CHECKED(EVP_DigestInit_ex(ctx, NULL, NULL));
+    SET_PAD_BYTE;
+finally:
+    return ok;
+}
+
 int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)
 {
     return EVP_DigestUpdate(ctx, p, l);
@@ -140,13 +156,13 @@
 int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)
 {
     unsigned int l;
-    return EVP_DigestFinal(ctx, md, &l);
+    return EVP_DigestFinal_ex(ctx, md, &l);
 }
 
 int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
 {
     unsigned int l;
-    return EVP_DigestFinal(ctx, md, &l);
+    return EVP_DigestFinal_ex(ctx, md, &l);
 }
 
 void keccak256_freectx(KECCAK256_CTX *ctx)
diff --git a/cbits/keccak.h b/cbits/keccak.h
--- a/cbits/keccak.h
+++ b/cbits/keccak.h
@@ -17,6 +17,7 @@
 // KECCAK-256
 KECCAK256_CTX *keccak256_newctx();
 int keccak256_init(KECCAK256_CTX *ctx);
+int keccak256_reset(KECCAK256_CTX *ctx);
 int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l);
 int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md);
 void keccak256_freectx(KECCAK256_CTX *ctx);
@@ -24,6 +25,7 @@
 // KECCAK-512
 KECCAK512_CTX *keccak512_newctx();
 int keccak512_init(KECCAK512_CTX *ctx);
+int keccak512_reset(KECCAK512_CTX *ctx);
 int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l);
 int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md);
 void keccak512_freectx(KECCAK512_CTX *ctx);
diff --git a/hashes.cabal b/hashes.cabal
--- a/hashes.cabal
+++ b/hashes.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name: hashes
-version: 0.2.2.1
+version: 0.2.3
 synopsis: Hash functions
 Description: Efficient implementations of hash functions
 homepage: https://github.com/larskuhtz/hs-hashes
diff --git a/src/Data/Hash/Class/Mutable.hs b/src/Data/Hash/Class/Mutable.hs
--- a/src/Data/Hash/Class/Mutable.hs
+++ b/src/Data/Hash/Class/Mutable.hs
@@ -29,6 +29,9 @@
 , updateShortByteString
 , updateStorable
 , updateByteArray
+
+-- * Resetable Hashes
+, ResetableHash(..)
 ) where
 
 import qualified Data.ByteString as B
@@ -47,7 +50,7 @@
 import Data.Hash.Class.Mutable.Internal
 
 -- -------------------------------------------------------------------------- --
--- Class of Salted Pure Hashes
+-- Class of Mutable Hashes
 
 class IncrementalHash a => Hash a where
     initialize :: IO (Context a)
diff --git a/src/Data/Hash/Class/Mutable/Internal.hs b/src/Data/Hash/Class/Mutable/Internal.hs
--- a/src/Data/Hash/Class/Mutable/Internal.hs
+++ b/src/Data/Hash/Class/Mutable/Internal.hs
@@ -12,15 +12,20 @@
 -- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>
 -- Stability: experimental
 --
--- Incremental Mutable Hashes
+-- Incremental and Resetable Mutable Hashes
 --
 module Data.Hash.Class.Mutable.Internal
-( IncrementalHash(..)
+(
+-- * Incremental Hashes
+  IncrementalHash(..)
 , updateByteString
 , updateByteStringLazy
 , updateShortByteString
 , updateStorable
 , updateByteArray
+
+-- * Resetable Hashes
+, ResetableHash(..)
 ) where
 
 import qualified Data.ByteString as B
@@ -103,4 +108,10 @@
   where
     size# = sizeofByteArray# a#
 {-# INLINE updateByteArray #-}
+
+-- -------------------------------------------------------------------------- --
+-- Class of Resetable Hashes
+
+class IncrementalHash a => ResetableHash a where
+    reset :: Context a -> IO ()
 
diff --git a/src/Data/Hash/Internal/OpenSSL.hs b/src/Data/Hash/Internal/OpenSSL.hs
--- a/src/Data/Hash/Internal/OpenSSL.hs
+++ b/src/Data/Hash/Internal/OpenSSL.hs
@@ -28,7 +28,7 @@
   Algorithm(..)
 , Ctx(..)
 , Digest(..)
-, newCtx
+, resetCtx
 , initCtx
 , updateCtx
 , finalCtx
@@ -67,6 +67,10 @@
 , Keccak256(..)
 , Keccak512(..)
 
+-- *** Unsafe finalize functions
+, finalizeKeccak256Ptr
+, finalizeKeccak512Ptr
+
 -- ** Blake2
 --
 -- $blake2
@@ -126,16 +130,17 @@
 #endif
     c_evp_ctx_free_ptr :: FunPtr (Ptr a -> IO ())
 
--- obsolete, superseeded by EVP_DigestInit_ex instead, but not deprecated
--- (beware in case this becomes a macro in future versions)
---
-foreign import ccall unsafe "opnessl/evp.h EVP_DigestInit"
-    c_evp_digest_init :: Ptr ctx -> Ptr alg -> IO Bool
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+foreign import ccall unsafe "openssl/evp.h EVP_DigestInit_ex2"
+#else
+foreign import ccall unsafe "openssl/evp.h EVP_DigestInit_ex"
+#endif
+    c_evp_digest_init :: Ptr ctx -> Ptr alg -> Ptr Void {- nullPtr -} -> IO Bool
 
-foreign import ccall unsafe "opnessl/evp.h EVP_DigestUpdate"
+foreign import ccall unsafe "openssl/evp.h EVP_DigestUpdate"
     c_evp_digest_update :: Ptr ctx -> Ptr d -> Int -> IO Bool
 
-foreign import ccall unsafe "opnessl/evp.h EVP_DigestFinal"
+foreign import ccall unsafe "openssl/evp.h EVP_DigestFinal_ex"
     c_evp_digest_final :: Ptr ctx -> Ptr d -> Int -> IO Bool
 
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
@@ -152,28 +157,40 @@
 #endif
     c_evp_get_size :: Algorithm -> IO Int
 
-newCtx :: IO (Ctx a)
-newCtx = fmap Ctx $ mask_ $ do
-    ptr <- c_evp_ctx_new
-    when (ptr == nullPtr) $ throw $ OpenSslException "failed to initialize context"
-    newForeignPtr c_evp_ctx_free_ptr ptr
-{-# INLINE newCtx #-}
-
+-- | Allocates and initializes a new context. The context may be reused by
+-- calling 'resetCtx' on it.
+--
 initCtx :: Algorithm -> IO (Ctx a)
 initCtx (Algorithm alg) = do
-    Ctx ctx <- newCtx
+    ctx <- mask_ $ do
+        ptr <- c_evp_ctx_new
+        when (ptr == nullPtr) $ throw $ OpenSslException "failed to create new context"
+        newForeignPtr c_evp_ctx_free_ptr ptr
     r <- withForeignPtr ctx $ \ptr ->
-        c_evp_digest_init ptr alg
+        c_evp_digest_init ptr alg nullPtr
     unless r $ throw $ OpenSslException "digest initialization failed"
     return $ Ctx ctx
 {-# INLINE initCtx #-}
 
+-- | Resets a context an initialize context.
+--
+resetCtx :: Ctx a -> IO ()
+resetCtx (Ctx ctx) = do
+    r <- withForeignPtr ctx $ \ptr ->
+        c_evp_digest_init ptr nullPtr nullPtr
+    unless r $ throw $ OpenSslException "digest re-initialization failed"
+{-# INLINE resetCtx #-}
+
+-- | Feed more data into an context.
+--
 updateCtx :: Ctx a -> Ptr Word8 -> Int -> IO ()
 updateCtx (Ctx ctx) d c = withForeignPtr ctx $ \ptr -> do
     r <- c_evp_digest_update ptr d c
     unless r $ throw $ OpenSslException "digest update failed"
 {-# INLINE updateCtx #-}
 
+-- | Finalize a hash and return the digest.
+--
 finalCtx :: Ctx a -> IO (Digest a)
 finalCtx (Ctx ctx) = withForeignPtr ctx $ \ptr -> do
     s <- c_evp_ctx_get0_md ptr >>= c_evp_get_size
@@ -200,6 +217,10 @@
     initialize = initCtx (algorithm @a)
     {-# INLINE initialize #-}
 
+instance OpenSslDigest a => ResetableHash (Digest a) where
+    reset = resetCtx
+    {-# INLINE reset #-}
+
 -- -------------------------------------------------------------------------- --
 -- Digests
 -- -------------------------------------------------------------------------- --
@@ -378,6 +399,9 @@
 foreign import ccall unsafe "keccak.h keccak256_init"
     c_keccak256_init :: Ptr ctx -> IO Bool
 
+foreign import ccall unsafe "keccak.h keccak256_reset"
+    c_keccak256_reset :: Ptr ctx -> IO Bool
+
 foreign import ccall unsafe "keccak.h keccak256_update"
     c_keccak256_update :: Ptr ctx -> Ptr Word8 -> Int -> IO Bool
 
@@ -400,7 +424,6 @@
     {-# INLINE update #-}
     {-# INLINE finalize #-}
 
-
 newKeccak256Ctx :: IO (Ctx Keccak256)
 newKeccak256Ctx = fmap Ctx $ mask_ $ do
     ptr <- c_keccak256_newctx
@@ -408,6 +431,25 @@
     newForeignPtr c_keccak256_freectx_ptr ptr
 {-# INLINE newKeccak256Ctx #-}
 
+resetKeccak256Ctx :: Ctx Keccak256 -> IO ()
+resetKeccak256Ctx (Ctx ctx) = do
+    r <- withForeignPtr ctx $ \ptr ->
+        c_keccak256_reset ptr
+    unless r $ throw $ OpenSslException "digest re-initialization failed"
+{-# INLINE resetKeccak256Ctx #-}
+
+-- | Low-Level function that writes the final digest directly into the provided
+-- pointer. The pointer must point to at least 64 bytes of allocated memory.
+-- This is not checked and a violation of this condition may result in a
+-- segmentation fault.
+--
+finalizeKeccak256Ptr :: Ctx Keccak256 -> Ptr Word8 -> IO ()
+finalizeKeccak256Ptr (Ctx ctx) dptr =
+    withForeignPtr ctx $ \cptr -> do
+        r <- c_keccak256_final cptr dptr
+        unless r $ throw $ OpenSslException "digest finalization failed"
+{-# INLINE finalizeKeccak256Ptr #-}
+
 instance Hash Keccak256 where
     initialize = do
         Ctx ctx <- newKeccak256Ctx
@@ -417,6 +459,10 @@
         return $ Ctx ctx
     {-# INLINE initialize #-}
 
+instance ResetableHash Keccak256 where
+    reset = resetKeccak256Ctx
+    {-# INLINE reset #-}
+
 -- KECCAK-512
 
 newtype Keccak512 = Keccak512 BS.ShortByteString
@@ -429,6 +475,9 @@
 foreign import ccall unsafe "keccak.h keccak512_init"
     c_keccak512_init :: Ptr ctx -> IO Bool
 
+foreign import ccall unsafe "keccak.h keccak512_reset"
+    c_keccak512_reset :: Ptr ctx -> IO Bool
+
 foreign import ccall unsafe "keccak.h keccak512_update"
     c_keccak512_update :: Ptr ctx -> Ptr Word8 -> Int -> IO Bool
 
@@ -451,7 +500,6 @@
     {-# INLINE update #-}
     {-# INLINE finalize #-}
 
-
 newKeccak512Ctx :: IO (Ctx Keccak512)
 newKeccak512Ctx = fmap Ctx $ mask_ $ do
     ptr <- c_keccak512_newctx
@@ -459,6 +507,25 @@
     newForeignPtr c_keccak512_freectx_ptr ptr
 {-# INLINE newKeccak512Ctx #-}
 
+resetKeccak512Ctx :: Ctx Keccak512 -> IO ()
+resetKeccak512Ctx (Ctx ctx) = do
+    r <- withForeignPtr ctx $ \ptr ->
+        c_keccak512_reset ptr
+    unless r $ throw $ OpenSslException "digest re-initialization failed"
+{-# INLINE resetKeccak512Ctx #-}
+
+-- | Low-Level function that writes the final digest directly into the provided
+-- pointer. The pointer must point to at least 64 bytes of allocated memory.
+-- This is not checked and a violation of this condition may result in a
+-- segmentation fault.
+--
+finalizeKeccak512Ptr :: Ctx Keccak512 -> Ptr Word8 -> IO ()
+finalizeKeccak512Ptr (Ctx ctx) dptr = do
+    withForeignPtr ctx $ \cptr -> do
+        r <- c_keccak512_final cptr dptr
+        unless r $ throw $ OpenSslException "digest finalization failed"
+{-# INLINE finalizeKeccak512Ptr #-}
+
 instance Hash Keccak512 where
     initialize = do
         Ctx ctx <- newKeccak512Ctx
@@ -467,6 +534,10 @@
         unless r $ throw $ OpenSslException "digest initialization failed"
         return $ Ctx ctx
     {-# INLINE initialize #-}
+
+instance ResetableHash Keccak512 where
+    reset = resetKeccak512Ctx
+    {-# INLINE reset #-}
 
 -- -------------------------------------------------------------------------- --
 -- Blake
diff --git a/src/Data/Hash/Keccak.hs b/src/Data/Hash/Keccak.hs
--- a/src/Data/Hash/Keccak.hs
+++ b/src/Data/Hash/Keccak.hs
@@ -33,6 +33,11 @@
   Keccak256(..)
 , Keccak512(..)
 , module Data.Hash.Class.Mutable
+
+-- *** Unsafe finalize functions
+, finalizeKeccak256Ptr
+, finalizeKeccak512Ptr
+
 ) where
 
 import Data.Hash.Class.Mutable
