diff --git a/nettle.cabal b/nettle.cabal
--- a/nettle.cabal
+++ b/nettle.cabal
@@ -1,5 +1,5 @@
 Name:                nettle
-Version:             0.2.0
+Version:             0.2.1
 Synopsis:            safe nettle binding
 Description:
   safe binding for the nettle (<http://www.lysator.liu.se/~nisse/nettle/nettle.html>) library.
@@ -47,6 +47,7 @@
   ghc-options:       -Wall -optc-O3 -fno-cse -fno-warn-tabs
   include-dirs:      src
   C-sources:         src/nettle-ciphers.c
+                     src/nettle-hash.c
   if flag(UsePkgConfig)
     PkgConfig-Depends: nettle
   else
diff --git a/src/Crypto/Nettle/ChaChaPoly1305.hs b/src/Crypto/Nettle/ChaChaPoly1305.hs
--- a/src/Crypto/Nettle/ChaChaPoly1305.hs
+++ b/src/Crypto/Nettle/ChaChaPoly1305.hs
@@ -38,7 +38,7 @@
 {-|
 Encrypt plain text and create a verification tag for the encrypted text and some additional data.
 @key@ and @nonce@ must not be reused together.
-The returned tag is 16 bytes long, but may be shortened for verification (loosing security).
+The returned tag is 16 bytes long, but may be shortened for verification (losing security).
 -}
 chaChaPoly1305Encrypt
 	:: B.ByteString                 -- ^ @key@ (must be 32 bytes)
diff --git a/src/Crypto/Nettle/Hash/ForeignImports.hsc b/src/Crypto/Nettle/Hash/ForeignImports.hsc
--- a/src/Crypto/Nettle/Hash/ForeignImports.hsc
+++ b/src/Crypto/Nettle/Hash/ForeignImports.hsc
@@ -205,7 +205,7 @@
 	c_sha3_224_init :: NettleHashInit
 foreign import ccall unsafe "nettle_sha3_224_update"
 	c_sha3_224_update :: NettleHashUpdate
-foreign import ccall unsafe "nettle_sha3_224_digest"
+foreign import ccall unsafe "hs_nettle_sha3_224_digest"
 	c_sha3_224_digest :: NettleHashDigest
 
 c_sha3_256_ctx_size :: Int
@@ -218,7 +218,7 @@
 	c_sha3_256_init :: NettleHashInit
 foreign import ccall unsafe "nettle_sha3_256_update"
 	c_sha3_256_update :: NettleHashUpdate
-foreign import ccall unsafe "nettle_sha3_256_digest"
+foreign import ccall unsafe "hs_nettle_sha3_256_digest"
 	c_sha3_256_digest :: NettleHashDigest
 
 c_sha3_384_ctx_size :: Int
@@ -231,7 +231,7 @@
 	c_sha3_384_init :: NettleHashInit
 foreign import ccall unsafe "nettle_sha3_384_update"
 	c_sha3_384_update :: NettleHashUpdate
-foreign import ccall unsafe "nettle_sha3_384_digest"
+foreign import ccall unsafe "hs_nettle_sha3_384_digest"
 	c_sha3_384_digest :: NettleHashDigest
 
 c_sha3_512_ctx_size :: Int
@@ -244,7 +244,7 @@
 	c_sha3_512_init :: NettleHashInit
 foreign import ccall unsafe "nettle_sha3_512_update"
 	c_sha3_512_update :: NettleHashUpdate
-foreign import ccall unsafe "nettle_sha3_512_digest"
+foreign import ccall unsafe "hs_nettle_sha3_512_digest"
 	c_sha3_512_digest :: NettleHashDigest
 
 c_md5_ctx_size :: Int
diff --git a/src/nettle-hash.c b/src/nettle-hash.c
new file mode 100644
--- /dev/null
+++ b/src/nettle-hash.c
@@ -0,0 +1,108 @@
+
+#include "nettle-hash.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#if (NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR < 2)
+
+void hs_nettle_sha3_224_digest(struct sha3_224_ctx *ctx, size_t length, uint8_t *digest) {
+	nettle_sha3_224_digest(ctx, length, digest);
+}
+
+void hs_nettle_sha3_256_digest(struct sha3_256_ctx *ctx, size_t length, uint8_t *digest) {
+	nettle_sha3_256_digest(ctx, length, digest);
+}
+
+void hs_nettle_sha3_384_digest(struct sha3_384_ctx *ctx, size_t length, uint8_t *digest) {
+	nettle_sha3_384_digest(ctx, length, digest);
+}
+
+void hs_nettle_sha3_512_digest(struct sha3_512_ctx *ctx, size_t length, uint8_t *digest) {
+	nettle_sha3_512_digest(ctx, length, digest);
+}
+
+#else
+
+/* copy some internal functions from nettle */
+#include <stddef.h>
+#include <string.h>
+
+#include <nettle/memxor.h>
+#include <nettle/macros.h>
+
+static void sha3_absorb(struct sha3_state *state, unsigned length, const uint8_t *data) {
+	assert((length & 7) == 0);
+#if WORDS_BIGENDIAN
+	{
+		uint64_t *p;
+		for (p = state->a; length > 0; p++, length -= 8, data += 8)
+			*p ^= LE_READ_UINT64(data);
+	}
+#else /* !WORDS_BIGENDIAN */
+	nettle_memxor(state->a, data, length);
+#endif
+
+	nettle_sha3_permute(state);
+}
+
+static void _pre_finalized_sha3_pad(struct sha3_state *state, unsigned block_size, uint8_t *block, unsigned pos) {
+	assert(pos < block_size);
+	block[pos++] = 1; /* in nettle 3.2 this became `6` */
+
+	memset(block + pos, 0, block_size - pos);
+	block[block_size - 1] |= 0x80;
+
+	sha3_absorb(state, block_size, block);
+}
+
+static void _nettle_write_le64(size_t length, uint8_t *dst, uint64_t *src) {
+	size_t i;
+	size_t words;
+	unsigned leftover;
+
+	words = length / 8;
+	leftover = length % 8;
+
+	for (i = 0; i < words; i++, dst += 8)
+		LE_WRITE_UINT64(dst, src[i]);
+
+	if (leftover) {
+		uint64_t word;
+
+		word = src[i];
+
+		do
+		{
+			*dst++ = word & 0xff;
+			word >>= 8;
+		} while (--leftover);
+	}
+}
+
+
+void hs_nettle_sha3_224_digest(struct sha3_224_ctx *ctx, size_t length, uint8_t *digest) {
+	_pre_finalized_sha3_pad(&ctx->state, SHA3_224_BLOCK_SIZE, ctx->block, ctx->index);
+	_nettle_write_le64(length, digest, ctx->state.a);
+	sha3_224_init(ctx);
+}
+
+void hs_nettle_sha3_256_digest(struct sha3_256_ctx *ctx, size_t length, uint8_t *digest) {
+	_pre_finalized_sha3_pad(&ctx->state, SHA3_256_BLOCK_SIZE, ctx->block, ctx->index);
+	_nettle_write_le64(length, digest, ctx->state.a);
+	sha3_256_init(ctx);
+}
+
+void hs_nettle_sha3_384_digest(struct sha3_384_ctx *ctx, size_t length, uint8_t *digest) {
+	_pre_finalized_sha3_pad(&ctx->state, SHA3_384_BLOCK_SIZE, ctx->block, ctx->index);
+	_nettle_write_le64(length, digest, ctx->state.a);
+	sha3_384_init(ctx);
+}
+
+void hs_nettle_sha3_512_digest(struct sha3_512_ctx *ctx, size_t length, uint8_t *digest) {
+	_pre_finalized_sha3_pad(&ctx->state, SHA3_512_BLOCK_SIZE, ctx->block, ctx->index);
+	_nettle_write_le64(length, digest, ctx->state.a);
+	sha3_512_init(ctx);
+}
+
+#endif
diff --git a/src/nettle-hash.h b/src/nettle-hash.h
--- a/src/nettle-hash.h
+++ b/src/nettle-hash.h
@@ -25,4 +25,9 @@
 
 #include <nettle/umac.h>
 
+void hs_nettle_sha3_224_digest(struct sha3_224_ctx *ctx, size_t length, uint8_t *digest);
+void hs_nettle_sha3_256_digest(struct sha3_256_ctx *ctx, size_t length, uint8_t *digest);
+void hs_nettle_sha3_384_digest(struct sha3_384_ctx *ctx, size_t length, uint8_t *digest);
+void hs_nettle_sha3_512_digest(struct sha3_512_ctx *ctx, size_t length, uint8_t *digest);
+
 #endif
