diff --git a/saltine.cabal b/saltine.cabal
--- a/saltine.cabal
+++ b/saltine.cabal
@@ -1,5 +1,5 @@
 name:                saltine
-version:             0.1.0.1
+version:             0.1.0.2
 synopsis:            Cryptography that's easy to digest (NaCl/libsodium bindings).
 description:
 
diff --git a/src/Crypto/Saltine/Core/AEAD.hs b/src/Crypto/Saltine/Core/AEAD.hs
--- a/src/Crypto/Saltine/Core/AEAD.hs
+++ b/src/Crypto/Saltine/Core/AEAD.hs
@@ -112,15 +112,15 @@
          -- ^ AAD
          -> Maybe ByteString
          -- ^ Message
-aeadOpen (Key key) (Nonce nonce) cipher aad =
+aeadOpen (Key key) (Nonce nonce) cipher aad = do
+  let clen   = S.length cipher
+      alen   = S.length aad
+  mlen <- clen `safeSubtract` Bytes.aead_xchacha20poly1305_ietf_ABYTES
   let (err, vec) = buildUnsafeByteString mlen $ \pm ->
         constByteStrings [key, cipher, aad, nonce] $ \
           [(pk, _), (pc, _), (pa, _), (pn, _)] ->
             c_aead_open pm nullPtr nullPtr pc (fromIntegral clen) pa (fromIntegral alen) pn pk
-  in hush . handleErrno err $ vec
-  where clen   = S.length cipher
-        alen   = S.length aad
-        mlen   = clen - Bytes.aead_xchacha20poly1305_ietf_ABYTES
+  hush . handleErrno err $ vec
 
 -- | Encrypts a message. It is infeasible for an attacker to decrypt
 -- the message so long as the 'Nonce' is never repeated.
diff --git a/src/Crypto/Saltine/Core/Box.hs b/src/Crypto/Saltine/Core/Box.hs
--- a/src/Crypto/Saltine/Core/Box.hs
+++ b/src/Crypto/Saltine/Core/Box.hs
@@ -199,16 +199,17 @@
         -- ^ Ciphertext (incl. authentication tag)
         -> Maybe ByteString
         -- ^ Message
-boxOpen (PK pk) (SK sk) (Nonce nonce) cipher =
+boxOpen (PK pk) (SK sk) (Nonce nonce) cipher = do
+  let msgLen = S.length cipher
+  bufSize <- msgLen `safeSubtract` Bytes.boxMac
   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->
         constByteStrings [pk, sk, cipher, nonce] $ \
           [(ppk, _), (psk, _), (pc, _), (pn, _)] ->
             c_box_open_easy pm pc (fromIntegral msgLen) pn ppk psk
-  in hush . handleErrno err $ vec
-  where
-    bufSize = S.length cipher - Bytes.boxMac
-    msgLen  = S.length cipher
+  hush . handleErrno err $ vec
 
+    
+
 -- | 'box' using a 'CombinedKey' and thus faster.
 boxAfterNM :: CombinedKey
            -> Nonce
@@ -232,17 +233,18 @@
                -- ^ Ciphertext (incl. authentication tag)
                -> Maybe ByteString
                -- ^ Message
-boxOpenAfterNM (CK ck) (Nonce nonce) cipher =
+boxOpenAfterNM (CK ck) (Nonce nonce) cipher = do
+  let msgLen = S.length cipher
+  bufSize <- msgLen `safeSubtract` Bytes.boxMac
   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->
         constByteStrings [ck, cipher, nonce] $ \
           [(pck, _), (pc, _), (pn, _)] ->
             c_box_open_easy_afternm pm pc (fromIntegral msgLen) pn pck
-  in hush . handleErrno err $ vec
-  where
-    bufSize = S.length cipher - Bytes.boxMac
-    msgLen  = S.length cipher
+  hush . handleErrno err $ vec
 
+    
 
+
 -- | Encrypts a message for sending to the owner of the public
 -- key. The message is unauthenticated, but permits integrity checking.
 boxSeal :: PublicKey -> ByteString -> IO ByteString
@@ -264,16 +266,14 @@
             -- ^ Ciphertext
             -> Maybe ByteString
             -- ^ Message
-boxSealOpen (PK pk) (SK sk) cipher =
+boxSealOpen (PK pk) (SK sk) cipher = do
+  let msgLen = S.length cipher
+  bufSize <- msgLen `safeSubtract` Bytes.sealedBox
   let (err, vec) = buildUnsafeByteString bufSize $ \pm ->
         constByteStrings [pk, sk, cipher] $ \
           [(ppk, _), (psk, _), (pc, _)] ->
           c_box_seal_open pm pc (fromIntegral msgLen) ppk psk
-  in hush . handleErrno err $ vec
-  where
-    bufSize = S.length cipher - Bytes.sealedBox
-    msgLen  = S.length cipher
-
+  hush . handleErrno err $ vec
 
 -- | Should always return a 0.
 foreign import ccall "crypto_box_keypair"
diff --git a/src/Crypto/Saltine/Internal/Util.hs b/src/Crypto/Saltine/Internal/Util.hs
--- a/src/Crypto/Saltine/Internal/Util.hs
+++ b/src/Crypto/Saltine/Internal/Util.hs
@@ -11,6 +11,11 @@
 import           Data.ByteString.Unsafe
 import           Data.Monoid
 
+-- | Returns @Nothing@ if the subtraction would result in an
+-- underflow or a negative number.
+safeSubtract :: (Ord a, Num a) => a -> a -> Maybe a
+x `safeSubtract` y = if y > x then Nothing else Just (x - y)
+
 -- | @snd . cycleSucc@ computes the 'succ' of a 'Bounded', 'Eq' 'Enum'
 -- with wraparound. The @fst . cycleSuc@ is whether the wraparound
 -- occurred (i.e. @fst . cycleSucc == (== maxBound)@).
diff --git a/tests/AEADProperties.hs b/tests/AEADProperties.hs
--- a/tests/AEADProperties.hs
+++ b/tests/AEADProperties.hs
@@ -10,6 +10,7 @@
 import           Crypto.Saltine.Class (decode,encode)
 import           Crypto.Saltine.Internal.ByteSizes as Bytes
 
+import           Control.Applicative
 import qualified Data.ByteString                      as S
 import           Test.Framework.Providers.QuickCheck2
 import           Test.Framework
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -13,6 +13,7 @@
 import ScalarMultProperties  (testScalarMult)
 import Crypto.Saltine
 
+import Data.Monoid
 import Test.Framework
 
 runOpts :: RunnerOptions
diff --git a/tests/SecretBoxProperties.hs b/tests/SecretBoxProperties.hs
--- a/tests/SecretBoxProperties.hs
+++ b/tests/SecretBoxProperties.hs
@@ -10,6 +10,7 @@
 import           Crypto.Saltine.Class
 import           Crypto.Saltine.Internal.ByteSizes as Bytes
 
+import           Control.Applicative
 import qualified Data.ByteString                      as S
 import           Test.Framework.Providers.QuickCheck2
 import           Test.Framework
