diff --git a/saltine.cabal b/saltine.cabal
--- a/saltine.cabal
+++ b/saltine.cabal
@@ -1,10 +1,10 @@
 name:                saltine
-version:             0.0.0.4
+version:             0.0.0.5
 synopsis:            Cryptography that's easy to digest (NaCl/libsodium bindings).
 description:
 
   /NaCl/ (pronounced \"salt\") is a new easy-to-use high-speed software
-  library for network communica tion, encryption, decryption,
+  library for network communication, encryption, decryption,
   signatures, etc. NaCl's goal is to provide all of the core
   operations needed to build higher-level cryptographic tools.
   .
@@ -21,13 +21,13 @@
 license:             MIT
 license-file:        LICENSE
 author:              Joseph Abrahamson
-maintainer:          Joseph Abrahamson <me@jspha.com>
+maintainer:          Max Amanshauser <max@lambdalifting.org>
 bug-reports:         http://github.com/tel/saltine/issues
 copyright:           Copyright (c) Joseph Abrahamson 2013
 category:            Cryptography
 build-type:          Simple
 cabal-version:       >=1.10
-tested-with:         GHC==7.6.3, GHC==7.8.4, GHC==7.10.1
+tested-with:         GHC==7.8.4, GHC==7.10.3, GHC==8.0.2
 
 source-repository head
   type: git
@@ -36,48 +36,47 @@
 library
   hs-source-dirs:     src
   exposed-modules:
-    Crypto.Saltine
-    Crypto.Saltine.Internal.ByteSizes
-    Crypto.Saltine.Core.SecretBox
-    Crypto.Saltine.Core.Box
-    Crypto.Saltine.Core.Stream
-    Crypto.Saltine.Core.Auth
-    Crypto.Saltine.Core.OneTimeAuth
-    Crypto.Saltine.Core.Sign
-    Crypto.Saltine.Core.Hash
-    Crypto.Saltine.Core.ScalarMult
-    Crypto.Saltine.Class
+                  Crypto.Saltine
+                  Crypto.Saltine.Internal.ByteSizes
+                  Crypto.Saltine.Core.SecretBox
+                  Crypto.Saltine.Core.Box
+                  Crypto.Saltine.Core.Stream
+                  Crypto.Saltine.Core.Auth
+                  Crypto.Saltine.Core.OneTimeAuth
+                  Crypto.Saltine.Core.Sign
+                  Crypto.Saltine.Core.Hash
+                  Crypto.Saltine.Core.ScalarMult
+                  Crypto.Saltine.Class
   other-modules:
-    Crypto.Saltine.Internal.Util
+                Crypto.Saltine.Internal.Util
   extra-libraries:    sodium
   cc-options:         -Wall
   ghc-options:        -Wall -funbox-strict-fields
   default-language:   Haskell2010
   build-depends:
-    base >= 4.5 && < 5,
-    bytestring,
-    profunctors
+                base >= 4.5 && < 5
+              , bytestring
+              , profunctors
 
 test-suite tests
   type:    exitcode-stdio-1.0
   main-is: Main.hs
   other-modules:
-    AuthProperties
-    BoxProperties
-    OneTimeAuthProperties
-    ScalarMultProperties
-    SecretBoxProperties
-    SignProperties
-    StreamProperties
-    Util
+                AuthProperties
+                BoxProperties
+                OneTimeAuthProperties
+                ScalarMultProperties
+                SecretBoxProperties
+                SignProperties
+                StreamProperties
+                Util
   ghc-options: -Wall -threaded -O0 -rtsopts
   hs-source-dirs: tests
   default-language: Haskell2010
   build-depends:
-    base >= 4.5 && < 5,
-    saltine,
-    bytestring,
-    vector,
-    QuickCheck,
-    test-framework-quickcheck2,
-    test-framework
+                base >= 4.5 && < 5
+              , saltine
+              , bytestring
+              , QuickCheck
+              , test-framework-quickcheck2
+              , test-framework
diff --git a/src/Crypto/Saltine.hs b/src/Crypto/Saltine.hs
--- a/src/Crypto/Saltine.hs
+++ b/src/Crypto/Saltine.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeFamilies             #-}
 
 module Crypto.Saltine (
   optimize,
@@ -10,11 +9,9 @@
 import Foreign.C
 import Crypto.Saltine.Core.SecretBox
 
--- | Runs Sodiums's optimizer. This has no semantic effect, but both
--- may boost the speed of Sodium after running it. It is recommended
--- in production environments. It is, however, NOT thread-safe so no
--- other Sodium functions should be called until it successfully
--- returns.
+-- | Runs Sodiums's initialization routine. This should be called before
+-- using any other function. It is thread-safe since libsodium 1.0.11,
+-- but not before.
 optimize :: IO ()
 optimize = do
   err <- c_sodiumInit
diff --git a/src/Crypto/Saltine/Class.hs b/src/Crypto/Saltine/Class.hs
--- a/src/Crypto/Saltine/Class.hs
+++ b/src/Crypto/Saltine/Class.hs
@@ -2,25 +2,24 @@
 -- Module      : Crypto.Saltine.Class
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Saltine type classes
 module Crypto.Saltine.Class (
   IsEncoding (..),
   IsNonce (..)
   ) where
 
-import Data.Profunctor
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
-import Control.Applicative
+import           Control.Applicative
+import           Data.Profunctor
+import           Data.ByteString     (ByteString)
 
 -- | Class for all keys and nonces in Saltine which have a
--- representation as 'V.Vector' of 'Word8'. 'encoded' is a 'Prism' of
--- type @Prism' (V.Vector Word8) a@ compatible with "Control.Lens" and
+-- representation as ByteString. 'encoded' is a 'Prism' of
+-- type @Prism' ByteString a@ compatible with "Control.Lens" and
 -- is automatically deduced.
 class IsEncoding a where
   encode  :: a -> ByteString
diff --git a/src/Crypto/Saltine/Core/Auth.hs b/src/Crypto/Saltine/Core/Auth.hs
--- a/src/Crypto/Saltine/Core/Auth.hs
+++ b/src/Crypto/Saltine/Core/Auth.hs
@@ -2,19 +2,19 @@
 -- Module      : Crypto.Saltine.Core.Auth
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
--- Secret-key message authentication: 
+--
+-- Secret-key message authentication:
 -- "Crypto.Saltine.Core.Auth"
--- 
+--
 -- The 'auth' function authenticates a message 'ByteString' using a
 -- secret key The function returns an authenticator. The 'verify'
 -- function checks if it's passed a correct authenticator of a message
 -- under the given secret key.
--- 
+--
 -- The 'auth' function, viewed as a function of the message for a
 -- uniform random key, is designed to meet the standard notion of
 -- unforgeability. This means that an attacker cannot find
@@ -25,17 +25,17 @@
 -- cipher block chaining message authentication code,\" Journal of
 -- Computer and System Sciences 61 (2000), 362–399;
 -- <http://www-cse.ucsd.edu/~mihir/papers/cbc.html>.
--- 
+--
 -- Saltine does not make any promises regarding \"strong\"
 -- unforgeability; perhaps one valid authenticator can be converted
 -- into another valid authenticator for the same message. NaCl also
 -- does not make any promises regarding \"truncated unforgeability.\"
--- 
+--
 -- "Crypto.Saltine.Core.Auth" is currently an implementation of
 -- HMAC-SHA-512-256, i.e., the first 256 bits of
 -- HMAC-SHA-512. HMAC-SHA-512-256 is conjectured to meet the standard
 -- notion of unforgeability.
--- 
+--
 -- This is version 2010.08.30 of the auth.html web page.
 module Crypto.Saltine.Core.Auth (
   Key, Authenticator,
@@ -43,37 +43,36 @@
   auth, verify
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
-
-import Control.Applicative
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
+import qualified Data.ByteString                   as S
+import           Data.ByteString                     (ByteString)
 
 -- $types
 
 -- | An opaque 'auth' cryptographic key.
-newtype Key = Key ByteString deriving (Eq, Ord)
+newtype Key           = Key ByteString deriving (Eq, Ord)
 
 -- | An opaque 'auth' authenticator.
-newtype Authenticator = Au ByteString deriving (Eq, Ord)
+newtype Authenticator = Au ByteString  deriving (Eq, Ord)
 
 instance IsEncoding Key where
-  decode v = case S.length v == Bytes.authKey of
-    True -> Just (Key v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.authKey
+           then Just (Key v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Key v) = v
   {-# INLINE encode #-}
 
 instance IsEncoding Authenticator where
-  decode v = case S.length v == Bytes.auth of
-    True -> Just (Au v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.auth
+           then Just (Au v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Au v) = v
   {-# INLINE encode #-}
@@ -86,10 +85,10 @@
 -- is infeasible to forge these authenticators without the key, even
 -- if an attacker observes many authenticators and messages and has
 -- the ability to influence the messages sent.
-auth :: Key 
-        -> ByteString
-        -- ^ Message
-        -> Authenticator
+auth :: Key
+     -> ByteString
+     -- ^ Message
+     -> Authenticator
 auth (Key key) msg =
   Au . snd . buildUnsafeCVector Bytes.auth $ \pa ->
     constVectors [key, msg] $ \[(pk, _), (pm, mlen)] ->
@@ -98,37 +97,37 @@
 -- | Checks to see if an authenticator is a correct proof that a
 -- message was signed by some key.
 verify :: Key
-          -> Authenticator
-          -> ByteString
-          -- ^ Message
-          -> Bool
-          -- ^ Is this message authentic?
+       -> Authenticator
+       -> ByteString
+       -- ^ Message
+       -> Bool
+       -- ^ Is this message authentic?
 verify (Key key) (Au a) msg =
   unsafeDidSucceed $ constVectors [key, msg, a] $ \[(pk, _), (pm, mlen), (pa, _)] ->
-  return $ c_auth_verify pa pm (fromIntegral mlen) pk
+    return $ c_auth_verify pa pm (fromIntegral mlen) pk
 
 foreign import ccall "crypto_auth"
   c_auth :: Ptr CChar
-            -- ^ Authenticator output buffer
-            -> Ptr CChar
-            -- ^ Constant message buffer
-            -> CULLong
-            -- ^ Length of message buffer
-            -> Ptr CChar
-            -- ^ Constant key buffer
-            -> IO CInt
-            -- ^ Always 0
+         -- ^ Authenticator output buffer
+         -> Ptr CChar
+         -- ^ Constant message buffer
+         -> CULLong
+         -- ^ Length of message buffer
+         -> Ptr CChar
+         -- ^ Constant key buffer
+         -> IO CInt
+         -- ^ Always 0
 
 -- | We don't even include this in the IO monad since all of the
 -- buffers are constant.
 foreign import ccall "crypto_auth_verify"
   c_auth_verify :: Ptr CChar
-                   -- ^ Constant authenticator buffer
-                   -> Ptr CChar
-                   -- ^ Constant message buffer
-                   -> CULLong
-                   -- ^ Length of message buffer
-                   -> Ptr CChar
-                   -- ^ Constant key buffer
-                   -> CInt
-                   -- ^ Success if 0, failure if -1
+                -- ^ Constant authenticator buffer
+                -> Ptr CChar
+                -- ^ Constant message buffer
+                -> CULLong
+                -- ^ Length of message buffer
+                -> Ptr CChar
+                -- ^ Constant key buffer
+                -> CInt
+                -- ^ Success if 0, failure if -1
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
@@ -2,28 +2,32 @@
 -- Module      : Crypto.Saltine.Core.Box
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
--- Public-key authenticated encryption:
+--
+-- Public-key cryptography abstraction:
 -- "Crypto.Saltine.Core.Box"
--- 
--- The 'box' function encrypts and authenticates a message
+--
+-- This module consists of functions dealing with two public-key
+-- cryptography concepts in libsodium.
+--
+-- The first one is an authenticated encryption scheme. In this
+-- scheme, the 'box' function encrypts and authenticates a message
 -- 'ByteString' using the sender's secret key, the receiver's public
 -- key, and a nonce. The 'boxOpen' function verifies and decrypts a
 -- ciphertext 'ByteString' using the receiver's secret key, the
 -- sender's public key, and a nonce. If the ciphertext fails
 -- verification, 'boxOpen' returns 'Nothing'.
--- 
--- The "Crypto.Saltine.Core.Box" module is designed to meet the
+--
+-- The set of box functions is designed to meet the
 -- standard notions of privacy and third-party unforgeability for a
 -- public-key authenticated-encryption scheme using nonces. For formal
 -- definitions see, e.g., Jee Hea An, "Authenticated encryption in the
 -- public-key setting: security notions and analyses,"
 -- <http://eprint.iacr.org/2001/079>.
--- 
+--
 -- Distinct messages between the same @{sender, receiver}@ set are
 -- required to have distinct nonces. For example, the
 -- lexicographically smaller public key can use nonce 1 for its first
@@ -33,13 +37,22 @@
 -- nonce 4 for its second message, nonce 6 for its third message,
 -- etc. Nonces are long enough that randomly generated nonces have
 -- negligible risk of collision.
--- 
+--
 -- There is no harm in having the same nonce for different messages if
 -- the @{sender, receiver}@ sets are different. This is true even if
 -- the sets overlap. For example, a sender can use the same nonce for
 -- two different messages if the messages are sent to two different
 -- public keys.
--- 
+--
+-- The second concept is sealed boxes, which provide encryption and
+-- preservation of integrity, but not authentication. Technically,
+-- the sender of a message generates a keypair, uses the regular
+-- box mechanism, attaches the public key to the message and then
+-- immediately destroys the private key. This is useful, e.g. when
+-- the receiver cannot know the sender's public key in advance and
+-- hence cannot use the regular box functions, or when you want to
+-- send messages anonymously.
+--
 -- The "Crypto.Saltine.Core.Box" module is not meant to provide
 -- non-repudiation. On the contrary: the crypto_box function
 -- guarantees repudiability. A receiver can freely modify a boxed
@@ -50,37 +63,38 @@
 -- <http://groups.google.com/group/sci.crypt/msg/ec5c18b23b11d82c>,
 -- crypto_box uses "public-key authenticators" rather than "public-key
 -- signatures."
--- 
+--
 -- Users who want public verifiability (or receiver-assisted public
 -- verifiability) should instead use signatures (or
 -- signcryption). Signatures are documented in the
 -- "Crypto.Saltine.Core.Sign" module.
--- 
+--
 -- "Crypto.Saltine.Core.Box" is @curve25519xsalsa20poly1305@, a
 -- particular combination of Curve25519, Salsa20, and Poly1305
 -- specified in "Cryptography in NaCl"
 -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured
 -- to meet the standard notions of privacy and third-party
 -- unforgeability.
--- 
+--
 -- This is version 2010.08.30 of the box.html web page.
 module Crypto.Saltine.Core.Box (
   SecretKey, PublicKey, Keypair, CombinedKey, Nonce,
   newKeypair, beforeNM, newNonce,
   box, boxOpen,
-  boxAfterNM, boxOpenAfterNM  
+  boxAfterNM, boxOpenAfterNM,
+  boxSeal, boxSealOpen
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import qualified Data.ByteString as S
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
+import qualified Data.ByteString                   as S
 import           Data.ByteString (ByteString)
 
-import Control.Applicative
 
 -- $types
 
@@ -88,9 +102,9 @@
 newtype SecretKey = SK ByteString deriving (Eq, Ord)
 
 instance IsEncoding SecretKey where
-  decode v = case S.length v == Bytes.boxSK of
-    True -> Just (SK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.boxSK
+           then Just (SK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (SK v) = v
   {-# INLINE encode #-}
@@ -99,9 +113,9 @@
 newtype PublicKey = PK ByteString deriving (Eq, Ord)
 
 instance IsEncoding PublicKey where
-  decode v = case S.length v == Bytes.boxPK of
-    True -> Just (PK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.boxPK
+           then Just (PK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (PK v) = v
   {-# INLINE encode #-}
@@ -113,9 +127,9 @@
 newtype CombinedKey = CK ByteString deriving (Eq, Ord)
 
 instance IsEncoding CombinedKey where
-  decode v = case S.length v == Bytes.boxBeforeNM of
-    True -> Just (CK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.boxBeforeNM
+           then Just (CK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (CK v) = v
   {-# INLINE encode #-}
@@ -124,15 +138,15 @@
 newtype Nonce = Nonce ByteString deriving (Eq, Ord)
 
 instance IsEncoding Nonce where
-  decode v = case S.length v == Bytes.boxNonce of
-    True -> Just (Nonce v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.boxNonce
+           then Just (Nonce v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Nonce v) = v
   {-# INLINE encode #-}
 
 instance IsNonce Nonce where
-  zero = Nonce (S.replicate Bytes.boxNonce 0)
+  zero            = Nonce (S.replicate Bytes.boxNonce 0)
   nudge (Nonce n) = Nonce (nudgeBS n)
 
 -- | Randomly generates a secret key and a corresponding public key.
@@ -142,7 +156,7 @@
   -- _err ought to always be 0.
   ((_err, sk), pk) <- buildUnsafeCVector' Bytes.boxPK $ \pkbuf ->
     buildUnsafeCVector' Bytes.boxSK $ \skbuf ->
-    c_box_keypair pkbuf skbuf
+      c_box_keypair pkbuf skbuf
   return (SK sk, PK pk)
 
 -- | Randomly generates a nonce for usage with 'box' and 'boxOpen'.
@@ -155,39 +169,39 @@
 beforeNM :: SecretKey -> PublicKey -> CombinedKey
 beforeNM (SK sk) (PK pk) = CK $ snd $ buildUnsafeCVector Bytes.boxBeforeNM $ \ckbuf ->
   constVectors [pk, sk] $ \[(ppk, _), (psk, _)] ->
-  c_box_beforenm ckbuf ppk psk
+    c_box_beforenm ckbuf ppk psk
 
 -- | Encrypts a message for sending to the owner of the public
 -- key. They must have your public key in order to decrypt the
 -- message. It is infeasible for an attacker to decrypt the message so
 -- long as the 'Nonce' is not repeated.
 box :: PublicKey -> SecretKey -> Nonce
-       -> ByteString
-       -- ^ Message
-       -> ByteString
-       -- ^ Ciphertext
+    -> ByteString
+    -- ^ Message
+    -> ByteString
+    -- ^ Ciphertext
 box (PK pk) (SK sk) (Nonce nonce) msg =
   unpad' . snd . buildUnsafeCVector len $ \pc ->
     constVectors [pk, sk, pad' msg, nonce] $ \
       [(ppk, _), (psk, _), (pm, _), (pn, _)] ->
-      c_box pc pm (fromIntegral len) pn ppk psk
+        c_box pc pm (fromIntegral len) pn ppk psk
   where len    = S.length msg + Bytes.boxZero
         pad'   = pad Bytes.boxZero
         unpad' = unpad Bytes.boxBoxZero
 
 -- | Decrypts a message sent from the owner of the public key. They
--- must have encrypted it using your secret key. Returns 'Nothing' if
+-- must have encrypted it using your public key. Returns 'Nothing' if
 -- the keys and message do not match.
 boxOpen :: PublicKey -> SecretKey -> Nonce
-           -> ByteString
-           -- ^ Ciphertext
-           -> Maybe ByteString
-           -- ^ Message
+        -> ByteString
+        -- ^ Ciphertext
+        -> Maybe ByteString
+        -- ^ Message
 boxOpen (PK pk) (SK sk) (Nonce nonce) cipher =
   let (err, vec) = buildUnsafeCVector len $ \pm ->
         constVectors [pk, sk, pad' cipher, nonce] $ \
           [(ppk, _), (psk, _), (pc, _), (pn, _)] ->
-          c_box_open pm pc (fromIntegral len) pn ppk psk
+            c_box_open pm pc (fromIntegral len) pn ppk psk
   in hush . handleErrno err $ unpad' vec
   where len    = S.length cipher + Bytes.boxBoxZero
         pad'   = pad Bytes.boxBoxZero
@@ -195,116 +209,174 @@
 
 -- | 'box' using a 'CombinedKey' and is thus faster.
 boxAfterNM :: CombinedKey -> Nonce
-              -> ByteString
-              -- ^ Message
-              -> ByteString
-              -- ^ Ciphertext
+           -> ByteString
+           -- ^ Message
+           -> ByteString
+           -- ^ Ciphertext
 boxAfterNM (CK ck) (Nonce nonce) msg =
   unpad' . snd . buildUnsafeCVector len $ \pc ->
     constVectors [ck, pad' msg, nonce] $ \
       [(pck, _), (pm, _), (pn, _)] ->
-      c_box_afternm pc pm (fromIntegral len) pn pck
+        c_box_afternm pc pm (fromIntegral len) pn pck
   where len    = S.length msg + Bytes.boxZero
         pad'   = pad Bytes.boxZero
         unpad' = unpad Bytes.boxBoxZero
 
 -- | 'boxOpen' using a 'CombinedKey' and is thus faster.
 boxOpenAfterNM :: CombinedKey -> Nonce
-           -> ByteString
-           -- ^ Ciphertext
-           -> Maybe ByteString
-           -- ^ Message
+               -> ByteString
+               -- ^ Ciphertext
+               -> Maybe ByteString
+               -- ^ Message
 boxOpenAfterNM (CK ck) (Nonce nonce) cipher =
   let (err, vec) = buildUnsafeCVector len $ \pm ->
         constVectors [ck, pad' cipher, nonce] $ \
           [(pck, _), (pc, _), (pn, _)] ->
-          c_box_open_afternm pm pc (fromIntegral len) pn pck
+            c_box_open_afternm pm pc (fromIntegral len) pn pck
   in hush . handleErrno err $ unpad' vec
   where len    = S.length cipher + Bytes.boxBoxZero
         pad'   = pad Bytes.boxBoxZero
         unpad' = unpad Bytes.boxZero
 
 
+-- | 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
+boxSeal (PK pk) msg = fmap snd . buildUnsafeCVector' strlen $ \pc ->
+    constVectors [pk, msg] $ \
+      [(ppk, _), (pm, _)] ->
+        c_box_seal pc pm (fromIntegral len) ppk
+  where strlen    = S.length msg + Bytes.sealedBox
+        len       = S.length msg
+
+-- | Decrypts a sealed box message. The message must have been
+-- encrypted using the receiver's public key.
+-- Returns 'Nothing' if keys and message do not match or integrity
+-- is violated.
+boxSealOpen :: PublicKey -> SecretKey
+            -> ByteString
+            -- ^ Ciphertext
+            -> Maybe ByteString
+            -- ^ Message
+boxSealOpen (PK pk) (SK sk) cipher =
+  let (err, vec) = buildUnsafeCVector strlen $ \pm ->
+        constVectors [pk, sk, cipher] $ \
+          [(ppk, _), (psk, _), (pc, _)] ->
+          c_box_seal_open pm pc (fromIntegral len) ppk psk
+  in hush . handleErrno err $ vec
+  where strlen    = S.length cipher - Bytes.sealedBox
+        len       = S.length cipher
+
+
 -- | Should always return a 0.
 foreign import ccall "crypto_box_keypair"
   c_box_keypair :: Ptr CChar
-                   -- ^ Public key
-                   -> Ptr CChar
-                   -- ^ Secret key
-                   -> IO CInt
-                   -- ^ Always 0
+                -- ^ Public key
+                -> Ptr CChar
+                -- ^ Secret key
+                -> IO CInt
+                -- ^ Always 0
 
 -- | The secretbox C API uses 0-padded C strings.
 foreign import ccall "crypto_box"
   c_box :: Ptr CChar
-           -- ^ Cipher 0-padded output buffer
-           -> Ptr CChar
-           -- ^ Constant 0-padded message input buffer
-           -> CULLong
-           -- ^ Length of message input buffer (incl. 0s)
-           -> Ptr CChar
-           -- ^ Constant nonce buffer
-           -> Ptr CChar
-           -- ^ Constant public key buffer
-           -> Ptr CChar
-           -- ^ Constant secret key buffer
-           -> IO CInt
-           -- ^ Always 0
+        -- ^ Cipher 0-padded output buffer
+        -> Ptr CChar
+        -- ^ Constant 0-padded message input buffer
+        -> CULLong
+        -- ^ Length of message input buffer (incl. 0s)
+        -> Ptr CChar
+        -- ^ Constant nonce buffer
+        -> Ptr CChar
+        -- ^ Constant public key buffer
+        -> Ptr CChar
+        -- ^ Constant secret key buffer
+        -> IO CInt
+        -- ^ Always 0
 
 -- | The secretbox C API uses 0-padded C strings.
 foreign import ccall "crypto_box_open"
   c_box_open :: Ptr CChar
-                -- ^ Message 0-padded output buffer
-                -> Ptr CChar
-                -- ^ Constant 0-padded ciphertext input buffer
-                -> CULLong
-                -- ^ Length of message input buffer (incl. 0s)
-                -> Ptr CChar
-                -- ^ Constant nonce buffer
-                -> Ptr CChar
-                -- ^ Constant public key buffer
-                -> Ptr CChar
-                -- ^ Constant secret key buffer
-                -> IO CInt
-                -- ^ 0 for success, -1 for failure to verify
+             -- ^ Message 0-padded output buffer
+             -> Ptr CChar
+             -- ^ Constant 0-padded ciphertext input buffer
+             -> CULLong
+             -- ^ Length of message input buffer (incl. 0s)
+             -> Ptr CChar
+             -- ^ Constant nonce buffer
+             -> Ptr CChar
+             -- ^ Constant public key buffer
+             -> Ptr CChar
+             -- ^ Constant secret key buffer
+             -> IO CInt
+             -- ^ 0 for success, -1 for failure to verify
 
 -- | Single target key precompilation.
 foreign import ccall "crypto_box_beforenm"
   c_box_beforenm :: Ptr CChar
-                    -- ^ Combined key output buffer
-                    -> Ptr CChar
-                    -- ^ Constant public key buffer
-                    -> Ptr CChar
-                    -- ^ Constant secret key buffer
-                    -> IO CInt
-                    -- ^ Always 0
+                 -- ^ Combined key output buffer
+                 -> Ptr CChar
+                 -- ^ Constant public key buffer
+                 -> Ptr CChar
+                 -- ^ Constant secret key buffer
+                 -> IO CInt
+                 -- ^ Always 0
 
 -- | Precompiled key crypto box. Uses 0-padded C strings.
 foreign import ccall "crypto_box_afternm"
   c_box_afternm :: Ptr CChar
-                   -- ^ Cipher 0-padded output buffer
-                   -> Ptr CChar
-                   -- ^ Constant 0-padded message input buffer
-                   -> CULLong
-                   -- ^ Length of message input buffer (incl. 0s)
-                   -> Ptr CChar
-                   -- ^ Constant nonce buffer
-                   -> Ptr CChar
-                   -- ^ Constant combined key buffer
-                   -> IO CInt
-                   -- ^ Always 0
+                -- ^ Cipher 0-padded output buffer
+                -> Ptr CChar
+                -- ^ Constant 0-padded message input buffer
+                -> CULLong
+                -- ^ Length of message input buffer (incl. 0s)
+                -> Ptr CChar
+                -- ^ Constant nonce buffer
+                -> Ptr CChar
+                -- ^ Constant combined key buffer
+                -> IO CInt
+                -- ^ Always 0
 
 -- | The secretbox C API uses 0-padded C strings.
 foreign import ccall "crypto_box_open_afternm"
   c_box_open_afternm :: Ptr CChar
-                        -- ^ Message 0-padded output buffer
-                        -> Ptr CChar
-                        -- ^ Constant 0-padded ciphertext input buffer
-                        -> CULLong
-                        -- ^ Length of message input buffer (incl. 0s)
-                        -> Ptr CChar
-                        -- ^ Constant nonce buffer
-                        -> Ptr CChar
-                        -- ^ Constant combined key buffer
-                        -> IO CInt
-                        -- ^ 0 for success, -1 for failure to verify
+                     -- ^ Message 0-padded output buffer
+                     -> Ptr CChar
+                     -- ^ Constant 0-padded ciphertext input buffer
+                     -> CULLong
+                     -- ^ Length of message input buffer (incl. 0s)
+                     -> Ptr CChar
+                     -- ^ Constant nonce buffer
+                     -> Ptr CChar
+                     -- ^ Constant combined key buffer
+                     -> IO CInt
+                     -- ^ 0 for success, -1 for failure to verify
+
+
+-- | The sealedbox C API uses C strings.
+foreign import ccall "crypto_box_seal"
+  c_box_seal :: Ptr CChar
+             -- ^ Cipher output buffer
+             -> Ptr CChar
+             -- ^ Constant message input buffer
+             -> CULLong
+             -- ^ Length of message input buffer
+             -> Ptr CChar
+             -- ^ Constant public key buffer
+             -> IO CInt
+             -- ^ Always 0
+
+-- | The sealedbox C API uses C strings.
+foreign import ccall "crypto_box_seal_open"
+  c_box_seal_open :: Ptr CChar
+                  -- ^ Message output buffer
+                  -> Ptr CChar
+                  -- ^ Constant ciphertext input buffer
+                  -> CULLong
+                  -- ^ Length of message input buffer
+                  -> Ptr CChar
+                  -- ^ Constant public key buffer
+                  -> Ptr CChar
+                  -- ^ Constant secret key buffer
+                  -> IO CInt
+                  -- ^ 0 for success, -1 for failure to decrypt
diff --git a/src/Crypto/Saltine/Core/Hash.hs b/src/Crypto/Saltine/Core/Hash.hs
--- a/src/Crypto/Saltine/Core/Hash.hs
+++ b/src/Crypto/Saltine/Core/Hash.hs
@@ -2,19 +2,19 @@
 -- Module      : Crypto.Saltine.Core.Hash
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Hashing: "Crypto.Saltine.Core.Hash"
--- 
+--
 -- The 'hash' function hashes a message 'ByteString' and returns a
 -- hash. Hashes are always of length 'Bytes.hash'. The 'shorthash'
 -- function hashes a message 'ByteString' with respect to a secret key
 -- and returns a very short hash. Short hashes are always of length
 -- 'Bytes.shorthash'.
--- 
+--
 -- The 'hash' function is designed to be usable as a strong component
 -- of DSA, RSA-PSS, key derivation, hash-based message-authentication
 -- codes, hash-based ciphers, and various other common
@@ -23,21 +23,21 @@
 -- security of the applications against generic attacks. In
 -- particular, the 'hash' function is designed to make finding
 -- collisions difficult.
--- 
+--
 -- 'hash' is currently an implementation of SHA-512. 'shorthash' is
 -- currently an implementation of SipHash-2-4
 -- (<https://131002.net/siphash/>).
--- 
+--
 -- There has been considerable degradation of public confidence in the
 -- security conjectures for many hash functions, including
 -- SHA-512. However, for the moment, there do not appear to be
 -- alternatives that inspire satisfactory levels of confidence. One
 -- can hope that NIST's SHA-3 competition will improve the situation.
--- 
+--
 -- Sodium includes an implementation of the Blake2 hash
 -- (<https://blake2.net/>) but since this is not standard NaCl nor was
 -- Blake2 selected to be SHA-3 the library doesn't bind it.
--- 
+--
 -- This is version 2010.08.30 of the hash.html web page. Information
 -- about SipHash has been added.
 module Crypto.Saltine.Core.Hash (
@@ -46,24 +46,23 @@
   shorthash, newShorthashKey
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
 import qualified Data.ByteString as S
 import           Data.ByteString (ByteString)
 
-import Control.Applicative
-
 -- | Computes a cryptographically collision-resistant hash making
 -- @hash m == hash m' ==> m == m'@ highly likely even when under
 -- attack.
 hash :: ByteString
-        -- ^ Message
-        -> ByteString
-        -- ^ Hash
+     -- ^ Message
+     -> ByteString
+     -- ^ Hash
 hash m = snd . buildUnsafeCVector Bytes.hash $ \ph ->
   constVectors [m] $ \[(pm, _)] -> c_hash ph pm (fromIntegral $ S.length m)
 
@@ -71,9 +70,9 @@
 newtype ShorthashKey = ShK ByteString deriving (Eq, Ord)
 
 instance IsEncoding ShorthashKey where
-  decode v = case S.length v == Bytes.shorthashKey of
-    True -> Just (ShK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.shorthashKey
+           then Just (ShK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (ShK v) = v
   {-# INLINE encode #-}
@@ -84,32 +83,32 @@
 
 -- | Computes a very short, fast keyed hash.
 shorthash :: ShorthashKey
-             -> ByteString
-             -- ^ Message
-             -> ByteString
-             -- ^ Hash
+          -> ByteString
+          -- ^ Message
+          -> ByteString
+          -- ^ Hash
 shorthash (ShK k) m = snd . buildUnsafeCVector Bytes.shorthash $ \ph ->
   constVectors [k, m] $ \[(pk, _), (pm, _)] ->
-  c_shorthash ph pm (fromIntegral $ S.length m) pk
-             
+    c_shorthash ph pm (fromIntegral $ S.length m) pk
+
 foreign import ccall "crypto_hash"
   c_hash :: Ptr CChar
-            -- ^ Output hash buffer
-            -> Ptr CChar
-            -- ^ Constant message buffer
-            -> CULLong
-            -- ^ Constant message buffer length
-            -> IO CInt
-            -- ^ Always 0
+         -- ^ Output hash buffer
+         -> Ptr CChar
+         -- ^ Constant message buffer
+         -> CULLong
+         -- ^ Constant message buffer length
+         -> IO CInt
+         -- ^ Always 0
 
 foreign import ccall "crypto_shorthash"
   c_shorthash :: Ptr CChar
-                 -- ^ Output hash buffer
-                 -> Ptr CChar
-                 -- ^ Constant message buffer
-                 -> CULLong
-                 -- ^ Message buffer length
-                 -> Ptr CChar
-                 -- ^ Constant Key buffer
-                 -> IO CInt
-                 -- ^ Always 0
+              -- ^ Output hash buffer
+              -> Ptr CChar
+              -- ^ Constant message buffer
+              -> CULLong
+              -- ^ Message buffer length
+              -> Ptr CChar
+              -- ^ Constant Key buffer
+              -> IO CInt
+              -- ^ Always 0
diff --git a/src/Crypto/Saltine/Core/OneTimeAuth.hs b/src/Crypto/Saltine/Core/OneTimeAuth.hs
--- a/src/Crypto/Saltine/Core/OneTimeAuth.hs
+++ b/src/Crypto/Saltine/Core/OneTimeAuth.hs
@@ -2,36 +2,36 @@
 -- Module      : Crypto.Saltine.Core.OneTimeAuth
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Secret-key single-message authentication:
 -- "Crypto.Saltine.Core.OneTimeAuth"
--- 
+--
 -- The 'auth' function authenticates a message 'ByteString' using a
 -- secret key The function returns an authenticator. The 'verify'
 -- function checks if it's passed a correct authenticator of a message
 -- under the given secret key.
--- 
+--
 -- The 'auth' function, viewed as a function of the message for a
 -- uniform random key, is designed to meet the standard notion of
 -- unforgeability after a single message. After the sender
 -- authenticates one message, an attacker cannot find authenticators
 -- for any other messages.
--- 
+--
 -- The sender must not use 'auth' to authenticate more than one
 -- message under the same key. Authenticators for two messages under
 -- the same key should be expected to reveal enough information to
 -- allow forgeries of authenticators on other messages.
--- 
+--
 -- "Crypto.Saltine.Core.OneTimeAuth" is
 -- @crypto_onetimeauth_poly1305@, an authenticator specified in
 -- "Cryptography in NaCl" (<http://nacl.cr.yp.to/valid.html>), Section
 -- 9. This authenticator is proven to meet the standard notion of
 -- unforgeability after a single message.
--- 
+--
 -- This is version 2010.08.30 of the onetimeauth.html web page.
 module Crypto.Saltine.Core.OneTimeAuth (
   Key, Authenticator,
@@ -39,37 +39,36 @@
   auth, verify
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
-
-import Control.Applicative
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
+import qualified Data.ByteString                   as S
+import           Data.ByteString                     (ByteString)
 
 -- $types
 
 -- | An opaque 'auth' cryptographic key.
-newtype Key = Key ByteString deriving (Eq, Ord)
+newtype Key           = Key ByteString deriving (Eq, Ord)
 
 -- | An opaque 'auth' authenticator.
-newtype Authenticator = Au ByteString deriving (Eq, Ord)
+newtype Authenticator = Au ByteString  deriving (Eq, Ord)
 
 instance IsEncoding Key where
-  decode v = case S.length v == Bytes.onetimeKey of
-    True -> Just (Key v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.onetimeKey
+           then Just (Key v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Key v) = v
   {-# INLINE encode #-}
 
 instance IsEncoding Authenticator where
-  decode v = case S.length v == Bytes.onetime of
-    True -> Just (Au v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.onetime
+           then Just (Au v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Au v) = v
   {-# INLINE encode #-}
@@ -82,48 +81,48 @@
 -- 'Authenticator' is /impossible/ to forge so long as the 'Key' is
 -- never used twice.
 auth :: Key
-        -> ByteString
-        -- ^ Message
-        -> Authenticator
+     -> ByteString
+     -- ^ Message
+     -> Authenticator
 auth (Key key) msg =
   Au . snd . buildUnsafeCVector Bytes.onetime $ \pa ->
     constVectors [key, msg] $ \[(pk, _), (pm, _)] ->
-    c_onetimeauth pa pm (fromIntegral $ S.length msg) pk
+      c_onetimeauth pa pm (fromIntegral $ S.length msg) pk
 
 -- | Verifies that an 'Authenticator' matches a given message and key.
 verify :: Key
-          -> Authenticator
-          -> ByteString
-          -- ^ Message
-          -> Bool
-          -- ^ Is this message authentic?
+       -> Authenticator
+       -> ByteString
+       -- ^ Message
+       -> Bool
+       -- ^ Is this message authentic?
 verify (Key key) (Au a) msg =
   unsafeDidSucceed $ constVectors [key, msg, a] $ \
     [(pk, _), (pm, _), (pa, _)] ->
-    return $ c_onetimeauth_verify pa pm (fromIntegral $ S.length msg) pk
+      return $ c_onetimeauth_verify pa pm (fromIntegral $ S.length msg) pk
 
 foreign import ccall "crypto_onetimeauth"
   c_onetimeauth :: Ptr CChar
-                   -- ^ Authenticator output buffer
-                   -> Ptr CChar
-                   -- ^ Constant message buffer
-                   -> CULLong
-                   -- ^ Length of message buffer
-                   -> Ptr CChar
-                   -- ^ Constant key buffer
-                   -> IO CInt
-                   -- ^ Always 0
+                -- ^ Authenticator output buffer
+                -> Ptr CChar
+                -- ^ Constant message buffer
+                -> CULLong
+                -- ^ Length of message buffer
+                -> Ptr CChar
+                -- ^ Constant key buffer
+                -> IO CInt
+                -- ^ Always 0
 
 -- | We don't even include this in the IO monad since all of the
 -- buffers are constant.
 foreign import ccall "crypto_onetimeauth_verify"
   c_onetimeauth_verify :: Ptr CChar
-                          -- ^ Constant authenticator buffer
-                          -> Ptr CChar
-                          -- ^ Constant message buffer
-                          -> CULLong
-                          -- ^ Length of message buffer
-                          -> Ptr CChar
-                          -- ^ Constant key buffer
-                          -> CInt
-                          -- ^ Success if 0, failure if -1
+                       -- ^ Constant authenticator buffer
+                       -> Ptr CChar
+                       -- ^ Constant message buffer
+                       -> CULLong
+                       -- ^ Length of message buffer
+                       -> Ptr CChar
+                       -- ^ Constant key buffer
+                       -> CInt
+                       -- ^ Success if 0, failure if -1
diff --git a/src/Crypto/Saltine/Core/ScalarMult.hs b/src/Crypto/Saltine/Core/ScalarMult.hs
--- a/src/Crypto/Saltine/Core/ScalarMult.hs
+++ b/src/Crypto/Saltine/Core/ScalarMult.hs
@@ -2,31 +2,31 @@
 -- Module      : Crypto.Saltine.Core.ScalarMult
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Scalar multiplication: "Crypto.Saltine.Core.ScalarMult"
--- 
+--
 -- The 'mult' function multiplies a group element by an integer of
 -- length 'Bytes.multScalar'. It returns the resulting group element
 -- of length 'Bytes.mult'. The 'multBase' function multiplies a
 -- standard group element by an integer of length
 -- 'Bytes.multScalar'. It returns the resulting group element of
 -- length 'Bytes.mult'.
--- 
+--
 -- The correspondence between strings and group elements depends on
 -- the primitive implemented by 'mult'. The correspondence is not
 -- necessarily injective in either direction, but it is compatible
 -- with scalar multiplication in the group. The correspondence does
 -- not necessarily include all group elements, but it does include all
 -- strings; i.e., every string represents at least one group element.
--- 
+--
 -- The correspondence between strings and integers also depends on the
 -- primitive implemented by 'mult'. Every string represents at least
 -- one integer.
--- 
+--
 -- 'mult' is designed to be strong as a component of various
 -- well-known \"hashed Diffie–Hellman\" applications. In particular,
 -- it is designed to make the \"computational Diffie–Hellman\" problem
@@ -36,33 +36,33 @@
 -- order, then it is annihilated by all represented scalars. This
 -- feature allows protocols to avoid validating membership in the
 -- subgroup generated by the standard base.
--- 
+--
 -- NaCl does not make any promises regarding the \"decisional
 -- Diffie–Hellman\" problem (DDH), the \"static Diffie–Hellman\"
 -- problem (SDH), etc. Users are responsible for hashing group
 -- elements.
--- 
+--
 -- 'mult' is the function @crypto_scalarmult_curve25519@ specified in
 -- \"Cryptography in NaCl\", Sections 2, 3, and 4
 -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured
 -- to be strong. For background see Bernstein, \"Curve25519: new
 -- Diffie-Hellman speed records,\" Lecture Notes in Computer Science
 -- 3958 (2006), 207–228, <http://cr.yp.to/papers.html#curve25519>.
--- 
+--
 -- This is version 2010.08.30 of the scalarmult.html web page.
 module Crypto.Saltine.Core.ScalarMult (
   Scalar, GroupElement,
   mult, multBase
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
+import           Foreign.C
+import           Foreign.Ptr
+import qualified Data.ByteString                   as S
+import           Data.ByteString                     (ByteString)
 
 -- $types
 
@@ -70,20 +70,20 @@
 newtype GroupElement = GE ByteString deriving (Eq)
 
 -- | A scalar integer.
-newtype Scalar = Sc ByteString deriving (Eq)
+newtype Scalar       = Sc ByteString deriving (Eq)
 
 instance IsEncoding GroupElement where
-  decode v = case S.length v == Bytes.mult of
-    True -> Just (GE v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.mult
+           then Just (GE v)
+           else Nothing
   {-# INLINE decode #-}
   encode (GE v) = v
   {-# INLINE encode #-}
 
 instance IsEncoding Scalar where
-  decode v = case S.length v == Bytes.multScalar of
-    True -> Just (Sc v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.multScalar
+           then Just (Sc v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Sc v) = v
   {-# INLINE encode #-}
@@ -91,27 +91,27 @@
 mult :: Scalar -> GroupElement -> GroupElement
 mult (Sc n) (GE p) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq ->
   constVectors [n, p] $ \[(pn, _), (pp, _)] ->
-  c_scalarmult pq pn pp
+    c_scalarmult pq pn pp
 
 multBase :: Scalar -> GroupElement
 multBase (Sc n) = GE . snd . buildUnsafeCVector Bytes.mult $ \pq ->
   constVectors [n] $ \[(pn, _)] ->
-  c_scalarmult_base pq pn
+    c_scalarmult_base pq pn
 
 foreign import ccall "crypto_scalarmult"
   c_scalarmult :: Ptr CChar
-                  -- ^ Output group element buffer
-                  -> Ptr CChar
-                  -- ^ Input integer buffer
-                  -> Ptr CChar
-                  -- ^ Input group element buffer
-                  -> IO CInt
-                  -- ^ Always 0
+               -- ^ Output group element buffer
+               -> Ptr CChar
+               -- ^ Input integer buffer
+               -> Ptr CChar
+               -- ^ Input group element buffer
+               -> IO CInt
+               -- ^ Always 0
 
 foreign import ccall "crypto_scalarmult_base"
   c_scalarmult_base :: Ptr CChar
-                       -- ^ Output group element buffer
-                       -> Ptr CChar
-                       -- ^ Input integer buffer
-                       -> IO CInt
-                       -- ^ Always 0
+                    -- ^ Output group element buffer
+                    -> Ptr CChar
+                    -- ^ Input integer buffer
+                    -> IO CInt
+                    -- ^ Always 0
diff --git a/src/Crypto/Saltine/Core/SecretBox.hs b/src/Crypto/Saltine/Core/SecretBox.hs
--- a/src/Crypto/Saltine/Core/SecretBox.hs
+++ b/src/Crypto/Saltine/Core/SecretBox.hs
@@ -2,20 +2,20 @@
 -- Module      : Crypto.Saltine.Core.SecretBox
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Secret-key authenticated encryption:
 -- "Crypto.Saltine.Core.SecretBox"
--- 
+--
 -- The 'secretbox' function encrypts and authenticates a message
 -- 'ByteString' using a secret key and a nonce. The 'secretboxOpen'
 -- function verifies and decrypts a ciphertext 'ByteString' using a
 -- secret key and a nonce. If the ciphertext fails validation,
 -- 'secretboxOpen' returns 'Nothing'.
--- 
+--
 -- The "Crypto.Saltine.Core.SecretBox" module is designed to meet
 -- the standard notions of privacy and authenticity for a secret-key
 -- authenticated-encryption scheme using nonces. For formal
@@ -23,19 +23,19 @@
 -- encryption: relations among notions and analysis of the generic
 -- composition paradigm," Lecture Notes in Computer Science 1976
 -- (2000), 531–545, <http://www-cse.ucsd.edu/~mihir/papers/oem.html>.
--- 
+--
 -- Note that the length is not hidden. Note also that it is the
 -- caller's responsibility to ensure the uniqueness of nonces—for
 -- example, by using nonce 1 for the first message, nonce 2 for the
 -- second message, etc. Nonces are long enough that randomly generated
 -- nonces have negligible risk of collision.
--- 
+--
 -- "Crypto.Saltine.Core.SecretBox" is
 -- @crypto_secretbox_xsalsa20poly1305@, a particular combination of
 -- Salsa20 and Poly1305 specified in \"Cryptography in NaCl\"
 -- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured
 -- to meet the standard notions of privacy and authenticity.
--- 
+--
 -- This is version 2010.08.30 of the secretbox.html web page.
 module Crypto.Saltine.Core.SecretBox (
   Key, Nonce,
@@ -43,16 +43,15 @@
   newKey, newNonce
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
-
-import Control.Applicative
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
+import qualified Data.ByteString                   as S
+import           Data.ByteString                     (ByteString)
 
 -- $types
 
@@ -60,9 +59,9 @@
 newtype Key = Key ByteString deriving (Eq, Ord)
 
 instance IsEncoding Key where
-  decode v = case S.length v == Bytes.secretBoxKey of
-    True -> Just (Key v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.secretBoxKey
+           then Just (Key v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Key v) = v
   {-# INLINE encode #-}
@@ -71,15 +70,15 @@
 newtype Nonce = Nonce ByteString deriving (Eq, Ord)
 
 instance IsEncoding Nonce where
-  decode v = case S.length v == Bytes.secretBoxNonce of
-    True -> Just (Nonce v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.secretBoxNonce
+           then Just (Nonce v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Nonce v) = v
   {-# INLINE encode #-}
 
 instance IsNonce Nonce where
-  zero = Nonce (S.replicate Bytes.secretBoxNonce 0)
+  zero            = Nonce (S.replicate Bytes.secretBoxNonce 0)
   nudge (Nonce n) = Nonce (nudgeBS n)
 
 -- | Creates a random key of the correct size for 'secretbox'.
@@ -93,15 +92,15 @@
 -- | Encrypts a message. It is infeasible for an attacker to decrypt
 -- the message so long as the 'Nonce' is never repeated.
 secretbox :: Key -> Nonce
-             -> ByteString
-             -- ^ Message
-             -> ByteString
-             -- ^ Ciphertext
+          -> ByteString
+          -- ^ Message
+          -> ByteString
+          -- ^ Ciphertext
 secretbox (Key key) (Nonce nonce) msg =
   unpad' . snd . buildUnsafeCVector len $ \pc ->
     constVectors [key, pad' msg, nonce] $ \
       [(pk, _), (pm, _), (pn, _)] ->
-      c_secretbox pc pm (fromIntegral len) pn pk
+        c_secretbox pc pm (fromIntegral len) pn pk
   where len    = S.length msg + Bytes.secretBoxZero
         pad'   = pad Bytes.secretBoxZero
         unpad' = unpad Bytes.secretBoxBoxZero
@@ -117,7 +116,7 @@
   let (err, vec) = buildUnsafeCVector len $ \pm ->
         constVectors [key, pad' cipher, nonce] $ \
           [(pk, _), (pc, _), (pn, _)] ->
-          c_secretbox_open pm pc (fromIntegral len) pn pk
+            c_secretbox_open pm pc (fromIntegral len) pn pk
   in hush . handleErrno err $ unpad' vec
   where len    = S.length cipher + Bytes.secretBoxBoxZero
         pad'   = pad Bytes.secretBoxBoxZero
@@ -126,28 +125,28 @@
 -- | The secretbox C API uses 0-padded C strings. Always returns 0.
 foreign import ccall "crypto_secretbox"
   c_secretbox :: Ptr CChar
-                 -- ^ Cipher 0-padded output buffer
-                 -> Ptr CChar
-                 -- ^ Constant 0-padded message input buffer
-                 -> CULLong
-                 -- ^ Length of message input buffer (incl. 0s)
-                 -> Ptr CChar
-                 -- ^ Constant nonce buffer
-                 -> Ptr CChar
-                 -- ^ Constant key buffer
-                 -> IO CInt
+              -- ^ Cipher 0-padded output buffer
+              -> Ptr CChar
+              -- ^ Constant 0-padded message input buffer
+              -> CULLong
+              -- ^ Length of message input buffer (incl. 0s)
+              -> Ptr CChar
+              -- ^ Constant nonce buffer
+              -> Ptr CChar
+              -- ^ Constant key buffer
+              -> IO CInt
 
 -- | The secretbox C API uses 0-padded C strings. Returns 0 if
 -- successful or -1 if verification failed.
 foreign import ccall "crypto_secretbox_open"
   c_secretbox_open :: Ptr CChar
-                      -- ^ Message 0-padded output buffer
-                      -> Ptr CChar
-                      -- ^ Constant 0-padded message input buffer
-                      -> CULLong
-                      -- ^ Length of message input buffer (incl. 0s)
-                      -> Ptr CChar
-                      -- ^ Constant nonce buffer
-                      -> Ptr CChar
-                      -- ^ Constant key buffer
-                      -> IO CInt
+                   -- ^ Message 0-padded output buffer
+                   -> Ptr CChar
+                   -- ^ Constant 0-padded message input buffer
+                   -> CULLong
+                   -- ^ Length of message input buffer (incl. 0s)
+                   -> Ptr CChar
+                   -- ^ Constant nonce buffer
+                   -> Ptr CChar
+                   -- ^ Constant key buffer
+                   -> IO CInt
diff --git a/src/Crypto/Saltine/Core/Sign.hs b/src/Crypto/Saltine/Core/Sign.hs
--- a/src/Crypto/Saltine/Core/Sign.hs
+++ b/src/Crypto/Saltine/Core/Sign.hs
@@ -2,20 +2,20 @@
 -- Module      : Crypto.Saltine.Core.Sign
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Signatures: "Crypto.Saltine.Core.Sign"
--- 
+--
 -- The 'newKeypair' function randomly generates a secret key and a
 -- corresponding public key. The 'sign' function signs a message
 -- 'ByteString' using the signer's secret key and returns the
 -- resulting signed message. The 'signOpen' function verifies the
 -- signature in a signed message using the signer's public key then
 -- returns the message without its signature.
--- 
+--
 -- "Crypto.Saltine.Core.Sign" is an EdDSA signature using
 -- elliptic-curve Curve25519 (see: <http://ed25519.cr.yp.to/>). See
 -- also, \"Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter
@@ -31,17 +31,17 @@
   sign, signOpen
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
-import Foreign.Marshal.Alloc
-import Foreign.Storable
-import System.IO.Unsafe
-import qualified Data.ByteString as S
-import           Data.ByteString (ByteString)
+import           Foreign.C
+import           Foreign.Ptr
+import           Foreign.Marshal.Alloc
+import           Foreign.Storable
+import           System.IO.Unsafe
+import qualified Data.ByteString                   as S
+import           Data.ByteString                     (ByteString)
 
 -- $types
 
@@ -49,9 +49,9 @@
 newtype SecretKey = SK ByteString deriving (Eq, Ord)
 
 instance IsEncoding SecretKey where
-  decode v = case S.length v == Bytes.signSK of
-    True -> Just (SK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.signSK
+           then Just (SK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (SK v) = v
   {-# INLINE encode #-}
@@ -60,9 +60,9 @@
 newtype PublicKey = PK ByteString deriving (Eq, Ord)
 
 instance IsEncoding PublicKey where
-  decode v = case S.length v == Bytes.signPK of
-    True -> Just (PK v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.signPK
+           then Just (PK v)
+           else Nothing
   {-# INLINE decode #-}
   encode (PK v) = v
   {-# INLINE encode #-}
@@ -78,21 +78,21 @@
   -- _err ought to always be 0.
   ((_err, sk), pk) <- buildUnsafeCVector' Bytes.signPK $ \pkbuf ->
     buildUnsafeCVector' Bytes.signSK $ \skbuf ->
-    c_sign_keypair pkbuf skbuf
+      c_sign_keypair pkbuf skbuf
   return (SK sk, PK pk)
 
 -- | Augments a message with a signature forming a \"signed
 -- message\".
 sign :: SecretKey
-        -> ByteString
-        -- ^ Message
-        -> ByteString
-        -- ^ Signed message
-sign (SK k) m = unsafePerformIO $ 
+     -> ByteString
+     -- ^ Message
+     -> ByteString
+     -- ^ Signed message
+sign (SK k) m = unsafePerformIO $
   alloca $ \psmlen -> do
     (_err, sm) <- buildUnsafeCVector' (len + Bytes.sign) $ \psmbuf ->
       constVectors [k, m] $ \[(pk, _), (pm, _)] ->
-      c_sign psmbuf psmlen pm (fromIntegral len) pk
+        c_sign psmbuf psmlen pm (fromIntegral len) pk
     smlen <- peek psmlen
     return $ S.take (fromIntegral smlen) sm
   where len = S.length m
@@ -101,54 +101,54 @@
 -- iff the signature was generated using the 'SecretKey' corresponding
 -- to the given 'PublicKey'. Returns 'Nothing' otherwise.
 signOpen :: PublicKey
-            -> ByteString
-            -- ^ Signed message
-            -> Maybe ByteString
-            -- ^ Maybe the restored message
+         -> ByteString
+         -- ^ Signed message
+         -> Maybe ByteString
+         -- ^ Maybe the restored message
 signOpen (PK k) sm = unsafePerformIO $
   alloca $ \pmlen -> do
     (err, m) <- buildUnsafeCVector' smlen $ \pmbuf ->
       constVectors [k, sm] $ \[(pk, _), (psm, _)] ->
-      c_sign_open pmbuf pmlen psm (fromIntegral smlen) pk
+        c_sign_open pmbuf pmlen psm (fromIntegral smlen) pk
     mlen <- peek pmlen
     case err of
       0 -> return $ Just $ S.take (fromIntegral mlen) m
-      _ -> return $ Nothing
+      _ -> return   Nothing
   where smlen = S.length sm
 
 
 foreign import ccall "crypto_sign_keypair"
   c_sign_keypair :: Ptr CChar
-                    -- ^ Public key output buffer
-                    -> Ptr CChar
-                    -- ^ Secret key output buffer
-                    -> IO CInt
-                    -- ^ Always 0
+                 -- ^ Public key output buffer
+                 -> Ptr CChar
+                 -- ^ Secret key output buffer
+                 -> IO CInt
+                 -- ^ Always 0
 
 foreign import ccall "crypto_sign"
   c_sign :: Ptr CChar
-            -- ^ Signed message output buffer
-            -> Ptr CULLong
-            -- ^ Length of signed message
-            -> Ptr CChar
-            -- ^ Constant message buffer
-            -> CULLong
-            -- ^ Length of message input buffer
-            -> Ptr CChar
-            -- ^ Constant secret key buffer
-            -> IO CInt
-            -- ^ Always 0
+         -- ^ Signed message output buffer
+         -> Ptr CULLong
+         -- ^ Length of signed message
+         -> Ptr CChar
+         -- ^ Constant message buffer
+         -> CULLong
+         -- ^ Length of message input buffer
+         -> Ptr CChar
+         -- ^ Constant secret key buffer
+         -> IO CInt
+         -- ^ Always 0
 
 foreign import ccall "crypto_sign_open"
   c_sign_open :: Ptr CChar
-                 -- ^ Message output buffer
-                 -> Ptr CULLong
-                 -- ^ Length of message
-                 -> Ptr CChar
-                 -- ^ Constant signed message buffer
-                 -> CULLong
-                 -- ^ Length of signed message buffer
-                 -> Ptr CChar
-                 -- ^ Public key buffer
-                 -> IO CInt
-                 -- ^ 0 if signature is verifiable, -1 otherwise
+              -- ^ Message output buffer
+              -> Ptr CULLong
+              -- ^ Length of message
+              -> Ptr CChar
+              -- ^ Constant signed message buffer
+              -> CULLong
+              -- ^ Length of signed message buffer
+              -> Ptr CChar
+              -- ^ Public key buffer
+              -> IO CInt
+              -- ^ 0 if signature is verifiable, -1 otherwise
diff --git a/src/Crypto/Saltine/Core/Stream.hs b/src/Crypto/Saltine/Core/Stream.hs
--- a/src/Crypto/Saltine/Core/Stream.hs
+++ b/src/Crypto/Saltine/Core/Stream.hs
@@ -2,21 +2,21 @@
 -- Module      : Crypto.Saltine.Core.Stream
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Secret-key encryption:
 -- "Crypto.Saltine.Core.Stream"
--- 
+--
 -- The 'stream' function produces a sized stream 'ByteString' as a
 -- function of a secret key and a nonce. The 'xor' function encrypts a
 -- message 'ByteString' using a secret key and a nonce.  The 'xor'
 -- function guarantees that the ciphertext has the same length as the
 -- plaintext, and is the @plaintext `xor` stream k n@. Consequently
 -- 'xor' can also be used to decrypt.
--- 
+--
 -- The 'stream' function, viewed as a function of the nonce for a
 -- uniform random key, is designed to meet the standard notion of
 -- unpredictability (\"PRF\"). For a formal definition see, e.g.,
@@ -29,22 +29,22 @@
 -- 'xor' with /a different nonce for each message/, the ciphertexts
 -- are indistinguishable from uniform random strings of the same
 -- length.
--- 
+--
 -- Note that the length is not hidden. Note also that it is the
 -- caller's responsibility to ensure the uniqueness of nonces—for
 -- example, by using nonce 1 for the first message, nonce 2 for the
 -- second message, etc. Nonces are long enough that randomly generated
 -- nonces have negligible risk of collision.
--- 
+--
 -- Saltine does not make any promises regarding the resistance of
 -- crypto_stream to \"related-key attacks.\" It is the caller's
 -- responsibility to use proper key-derivation functions.
--- 
+--
 -- "Crypto.Saltine.Core.Stream" is @crypto_stream_xsalsa20@, a
 -- particular cipher specified in \"Cryptography in NaCl\"
 -- (<http://nacl.cr.yp.to/valid.html>), Section 7. This cipher is
 -- conjectured to meet the standard notion of unpredictability.
--- 
+--
 -- This is version 2010.08.30 of the stream.html web page.
 
 module Crypto.Saltine.Core.Stream (
@@ -53,26 +53,25 @@
   stream, xor
   ) where
 
-import Crypto.Saltine.Class
-import Crypto.Saltine.Internal.Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Internal.Util
 import qualified Crypto.Saltine.Internal.ByteSizes as Bytes
 
-import Foreign.C
-import Foreign.Ptr
+import           Control.Applicative
+import           Foreign.C
+import           Foreign.Ptr
 import qualified Data.ByteString as S
 import           Data.ByteString (ByteString)
 
-import Control.Applicative
-
 -- $types
 
 -- | An opaque 'stream' cryptographic key.
 newtype Key = Key ByteString deriving (Eq, Ord)
 
 instance IsEncoding Key where
-  decode v = case S.length v == Bytes.streamKey of
-    True -> Just (Key v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.streamKey
+           then Just (Key v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Key v) = v
   {-# INLINE encode #-}
@@ -85,9 +84,9 @@
   nudge (Nonce n) = Nonce (nudgeBS n)
 
 instance IsEncoding Nonce where
-  decode v = case S.length v == Bytes.streamNonce of
-    True -> Just (Nonce v)
-    False -> Nothing
+  decode v = if S.length v == Bytes.streamNonce
+           then Just (Nonce v)
+           else Nothing
   {-# INLINE decode #-}
   encode (Nonce v) = v
   {-# INLINE encode #-}
@@ -105,8 +104,8 @@
 -- 'Nonce'. These streams are indistinguishable from random noise so
 -- long as the 'Nonce' is not used more than once.
 stream :: Key -> Nonce -> Int
-          -> ByteString
-          -- ^ Cryptographic stream
+       -> ByteString
+       -- ^ Cryptographic stream
 stream (Key key) (Nonce nonce) n =
   snd . buildUnsafeCVector n $ \ps ->
     constVectors [key, nonce] $ \[(pk, _), (pn, _)] ->
@@ -119,11 +118,11 @@
 -- for encryption and decryption, it is /possible for an attacker to/
 -- /manipulate the message in transit without detection/. USE AT YOUR
 -- OWN RISK.
-xor :: Key -> Nonce 
-       -> ByteString
-       -- ^ Message
-       -> ByteString
-       -- ^ Ciphertext
+xor :: Key -> Nonce
+    -> ByteString
+    -- ^ Message
+    -> ByteString
+    -- ^ Ciphertext
 xor (Key key) (Nonce nonce) msg =
   snd . buildUnsafeCVector len $ \pc ->
     constVectors [key, nonce, msg] $ \[(pk, _), (pn, _), (pm, _)] ->
@@ -132,26 +131,26 @@
 
 foreign import ccall "crypto_stream"
   c_stream :: Ptr CChar
-              -- ^ Stream output buffer
-              -> CULLong
-              -- ^ Length of stream to generate
-              -> Ptr CChar
-              -- ^ Constant nonce buffer
-              -> Ptr CChar
-              -- ^ Constant key buffer
-              -> IO CInt
-              -- ^ Always 0
+           -- ^ Stream output buffer
+           -> CULLong
+           -- ^ Length of stream to generate
+           -> Ptr CChar
+           -- ^ Constant nonce buffer
+           -> Ptr CChar
+           -- ^ Constant key buffer
+           -> IO CInt
+           -- ^ Always 0
 
 foreign import ccall "crypto_stream_xor"
   c_stream_xor :: Ptr CChar
-                  -- ^ Ciphertext output buffer
-                  -> Ptr CChar
-                  -- ^ Constant message buffer
-                  -> CULLong
-                  -- ^ Length of message buffer
-                  -> Ptr CChar
-                  -- ^ Constant nonce buffer
-                  -> Ptr CChar
-                  -- ^ Constant key buffer
-                  -> IO CInt
-                  -- ^ Always 0
+               -- ^ Ciphertext output buffer
+               -> Ptr CChar
+               -- ^ Constant message buffer
+               -> CULLong
+               -- ^ Length of message buffer
+               -> Ptr CChar
+               -- ^ Constant nonce buffer
+               -> Ptr CChar
+               -- ^ Constant key buffer
+               -> IO CInt
+               -- ^ Always 0
diff --git a/src/Crypto/Saltine/Internal/ByteSizes.hs b/src/Crypto/Saltine/Internal/ByteSizes.hs
--- a/src/Crypto/Saltine/Internal/ByteSizes.hs
+++ b/src/Crypto/Saltine/Internal/ByteSizes.hs
@@ -3,17 +3,17 @@
 -- Module      : Crypto.Saltine.Core.ScalarMult
 -- Copyright   : (c) Joseph Abrahamson 2013
 -- License     : MIT
--- 
+--
 -- Maintainer  : me@jspha.com
 -- Stability   : experimental
 -- Portability : non-portable
--- 
+--
 -- Various sizes
--- 
+--
 -- While technically these sizes are hidden behind opaque newtype
 -- wrappers, they can be useful for computation and sizing and are
 -- thus exposed.
--- 
+--
 -- As of @libsodium-4.1@ some of these sizes are not exported and thus
 -- are hardcoded here. This limitation should be removed in later
 -- versions of @libsodium@.
@@ -28,6 +28,7 @@
   boxBoxZero,
   boxMac,
   boxBeforeNM,
+  sealedBox,
   onetime,
   onetimeKey,
   mult,
@@ -44,7 +45,6 @@
   hash,
   shorthash,
   shorthashKey
-  
   ) where
 
 import Foreign.C
@@ -52,7 +52,8 @@
 -- Constants for
 
 auth, authKey :: Int
-boxPK, boxSK, boxNonce, boxZero, boxBoxZero, boxMac, boxBeforeNM :: Int
+boxPK, boxSK, boxNonce, boxZero, boxBoxZero :: Int
+boxMac, boxBeforeNM, sealedBox :: Int
 onetime, onetimeKey :: Int
 mult, multScalar :: Int
 secretBoxKey, secretBoxNonce, secretBoxZero, secretBoxBoxZero :: Int
@@ -64,7 +65,7 @@
 -- Authentication
 -- | Size of a @crypto_auth@ authenticator.
 auth    = fromIntegral c_crypto_auth_bytes
--- | Size of a @crypto_auth@ authenticator key. 
+-- | Size of a @crypto_auth@ authenticator key.
 authKey = fromIntegral c_crypto_auth_keybytes
 
 -- Box
@@ -85,6 +86,11 @@
 boxBeforeNM =
   fromIntegral c_crypto_box_beforenmbytes
 
+-- SealedBox
+-- | Amount by which ciphertext is longer than plaintext
+-- in sealed boxes
+sealedBox = fromIntegral c_crypto_box_sealbytes
+
 -- OneTimeAuth
 -- | Size of a @crypto_onetimeauth@ authenticator.
 onetime    = fromIntegral c_crypto_onetimeauth_bytes
@@ -157,7 +163,11 @@
   c_crypto_box_boxzerobytes :: CSize
 foreign import ccall "crypto_box_macbytes"
   c_crypto_box_macbytes :: CSize
-                           
+
+-- src/libsodium/crypto_box_seal.c
+foreign import ccall "crypto_box_sealbytes"
+  c_crypto_box_sealbytes :: CSize
+
 -- src/libsodium/crypto_onetimeauth/crypto_onetimeauth.c
 foreign import ccall "crypto_onetimeauth_bytes"
   c_crypto_onetimeauth_bytes :: CSize
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
@@ -1,13 +1,14 @@
 module Crypto.Saltine.Internal.Util where
 
-import Foreign.C
-import Foreign.Ptr
-import System.IO.Unsafe
+import           Foreign.C
+import           Foreign.Ptr
+import           System.IO.Unsafe
 
-import Data.Monoid
-import qualified Data.ByteString as S
-import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe
+import           Control.Applicative
+import qualified Data.ByteString        as S
+import           Data.ByteString          (ByteString)
+import           Data.ByteString.Unsafe
+import           Data.Monoid
 
 -- | @snd . cycleSucc@ computes the 'succ' of a 'Bounded', 'Eq' 'Enum'
 -- with wraparound. The @fst . cycleSuc@ is whether the wraparound
@@ -20,16 +21,17 @@
 -- it.
 nudgeBS :: ByteString -> ByteString
 nudgeBS i = fst $ S.unfoldrN (S.length i) go (True, i) where
-  go (toSucc, bs) =
-    do (hd, tl) <- S.uncons bs
-       let (top, hd') = cycleSucc hd
-       if toSucc
-         then return (hd', (top, tl))
-         else return (hd, (top && toSucc, tl))
+  go (toSucc, bs) = do
+    (hd, tl)      <- S.uncons bs
+    let (top, hd') = cycleSucc hd
 
+    if   toSucc
+    then return (hd', (top, tl))
+    else return (hd, (top && toSucc, tl))
+
 -- | Computes the orbit of a endomorphism... in a very brute force
 -- manner. Exists just for the below property.
--- 
+--
 -- prop> length . orbit nudgeBS . S.pack . replicate 0 == (256^)
 orbit :: Eq a => (a -> a) -> a -> [a]
 orbit f a0 = orbit' (f a0) where
@@ -66,7 +68,7 @@
 buildUnsafeCVector' :: Int -> (Ptr CChar -> IO b) -> IO (b, ByteString)
 buildUnsafeCVector' n k = do
   let bs = S.replicate n 0
-  out <- unsafeUseAsCString bs k
+  out   <- unsafeUseAsCString bs k
   return (out, bs)
 
 -- | Extremely unsafe function, use with utmost care! Builds a new
@@ -80,7 +82,7 @@
 -- @/dev/urandom@.
 randomVector :: Int -> IO ByteString
 randomVector n =
-  fmap snd $ buildUnsafeCVector' n (`c_randombytes_buf` fromIntegral n)
+  snd <$> buildUnsafeCVector' n (`c_randombytes_buf` fromIntegral n)
 
 -- | To prevent a dependency on package 'errors'
 hush :: Either s a -> Maybe a
diff --git a/tests/AuthProperties.hs b/tests/AuthProperties.hs
--- a/tests/AuthProperties.hs
+++ b/tests/AuthProperties.hs
@@ -5,7 +5,6 @@
   ) where
 
 import Util
-
 import Crypto.Saltine.Core.Auth
 
 import Test.Framework.Providers.QuickCheck2
@@ -17,6 +16,6 @@
   return $ testGroup "...Internal.Auth" [
 
     testProperty "Authenticates message"
-    $ \(Message bs) -> verify k (auth k bs) bs  == True
+    $ \(Message bs) -> verify k (auth k bs) bs == True
 
     ]
diff --git a/tests/BoxProperties.hs b/tests/BoxProperties.hs
--- a/tests/BoxProperties.hs
+++ b/tests/BoxProperties.hs
@@ -4,17 +4,14 @@
   testBox
   ) where
 
-import Util
-
-import Crypto.Saltine.Core.Box
-
-import qualified Data.ByteString as S
-
-import Test.Framework.Providers.QuickCheck2
-import Test.Framework
+import           Util
+import           Crypto.Saltine.Core.Box
+import qualified Data.ByteString                      as S
 
-import Test.QuickCheck.Property
-import Test.QuickCheck.Monadic
+import           Test.Framework.Providers.QuickCheck2
+import           Test.Framework
+import           Test.QuickCheck.Property
+import           Test.QuickCheck.Monadic
 
 -- | Ciphertext can be decrypted
 rightInverseProp :: Keypair -> Keypair -> Nonce -> Message -> Bool
@@ -67,7 +64,6 @@
 
 testBox :: Test
 testBox = buildTest $ do
-
   (sk1, pk1) <- newKeypair
   (sk2, pk2) <- newKeypair
   let ck_1for2 = beforeNM sk1 pk2
@@ -78,39 +74,37 @@
   return $ testGroup "...Internal.Box" [
 
     testGroup "Can decrypt ciphertext using..." [
-       
+
        testProperty "... public key/secret key"
        $ rightInverseProp (sk1, pk1) (sk2, pk2) n1 ,
-       
+
        testProperty "... combined key"
        $ rightInverseAfterNMProp ck_1for2 ck_2for1 n1
-       
+
        ],
 
     testGroup "Fail to verify ciphertext when..." [
-      
+
       testProperty "... not using proper secret key"
       $ rightInverseFailureProp1 (sk1, pk1) (sk2, pk2) n1,
-      
+
       testProperty "... not actually sent to you"
       $ rightInverseFailureProp2 (sk1, pk1) (sk2, pk2) n1,
-      
+
       testProperty "... ciphertext has been perturbed"
       $ rightInverseFailureProp3 (sk1, pk1) (sk2, pk2) n1,
-      
+
       testProperty "... using the wrong nonce"
       $ cannotDecryptNonceProp (sk1, pk1) (sk2, pk2) n1 n2,
-      
+
       testProperty "... using the wrong combined key"
       $ rightInverseFailureAfterNMProp1 ck_1for2 ck_2for1 n1
-      
+
       ],
 
     testGroup "(properties)" [
 
       testProperty "beforeNM is anti-symmetric" beforeNMCreateSecretKeyProp
-      
+
       ]
     ]
-    
-       
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -2,19 +2,21 @@
 
 module Main where
 
-import SecretBoxProperties (testSecretBox)
-import BoxProperties (testBox)
-import StreamProperties (testStream)
-import AuthProperties (testAuth)
+import SecretBoxProperties   (testSecretBox)
+import BoxProperties         (testBox)
+import SealedBoxProperties   (testSealedBox)
+import StreamProperties      (testStream)
+import AuthProperties        (testAuth)
 import OneTimeAuthProperties (testOneTimeAuth)
-import SignProperties (testSign)
-import ScalarMultProperties (testScalarMult)
+import SignProperties        (testSign)
+import ScalarMultProperties  (testScalarMult)
 
 import Test.Framework
 
 main :: IO ()
 main = defaultMain [
   testBox,
+  testSealedBox,
   testSecretBox,
   testStream,
   testAuth,
diff --git a/tests/OneTimeAuthProperties.hs b/tests/OneTimeAuthProperties.hs
--- a/tests/OneTimeAuthProperties.hs
+++ b/tests/OneTimeAuthProperties.hs
diff --git a/tests/ScalarMultProperties.hs b/tests/ScalarMultProperties.hs
--- a/tests/ScalarMultProperties.hs
+++ b/tests/ScalarMultProperties.hs
@@ -4,16 +4,14 @@
   testScalarMult
   ) where
 
-import Util
-
-import Crypto.Saltine.Class
-import Crypto.Saltine.Core.ScalarMult
-
-import qualified Data.ByteString as S
-import Data.Maybe (fromJust)
+import           Util
+import           Crypto.Saltine.Class
+import           Crypto.Saltine.Core.ScalarMult
 
-import Test.Framework.Providers.QuickCheck2
-import Test.Framework
+import qualified Data.ByteString                      as S
+import           Data.Maybe                             (fromJust)
+import           Test.Framework.Providers.QuickCheck2
+import           Test.Framework
 
 -- Test vectors extracted from "Cryptography in NaCl",
 -- http://cr.yp.to/highspeed/naclcrypto-20090310.pdf
@@ -47,7 +45,7 @@
     ,0x76,0xf0,0x9b,0x3c,0x1e,0x16,0x17,0x42]
 
 testScalarMult :: Test
-testScalarMult = buildTest $ do
+testScalarMult = buildTest $
   return $ testGroup "...Internal.ScalarMult" [
 
     testProperty "mult a (multBase a) /= multBase a"
diff --git a/tests/SecretBoxProperties.hs b/tests/SecretBoxProperties.hs
--- a/tests/SecretBoxProperties.hs
+++ b/tests/SecretBoxProperties.hs
@@ -4,14 +4,12 @@
   testSecretBox
   ) where
 
-import Util
-
-import Crypto.Saltine.Core.SecretBox
-
-import qualified Data.ByteString as S
+import           Util
+import           Crypto.Saltine.Core.SecretBox
 
-import Test.Framework.Providers.QuickCheck2
-import Test.Framework
+import qualified Data.ByteString                      as S
+import           Test.Framework.Providers.QuickCheck2
+import           Test.Framework
 
 -- | Ciphertext can be decrypted
 rightInverseProp :: Key -> Nonce -> Message -> Bool
@@ -55,6 +53,6 @@
 
       testProperty "... using the wrong nonce"
       $ cannotDecryptNonceProp k1 n1 n2
-      
+
       ]
     ]
diff --git a/tests/SignProperties.hs b/tests/SignProperties.hs
--- a/tests/SignProperties.hs
+++ b/tests/SignProperties.hs
@@ -4,15 +4,13 @@
   testSign
   ) where
 
-import Util
-
-import Crypto.Saltine.Core.Sign
-
-import qualified Data.ByteString as S
+import           Util
+import           Crypto.Saltine.Core.Sign
 
-import Test.Framework.Providers.QuickCheck2
-import Test.Framework
-import Test.QuickCheck
+import qualified Data.ByteString                      as S
+import           Test.Framework.Providers.QuickCheck2
+import           Test.Framework
+import           Test.QuickCheck
 
 testSign :: Test
 testSign = buildTest $ do
@@ -28,6 +26,6 @@
     $ \(Message bs) -> S.length (sign sk1 bs) >= S.length bs,
 
     testProperty "Rejects message with mismatched key"
-    $ \(Message bs) -> (not $ S.null bs) ==> signOpen pk2 (sign sk1 bs) == Nothing
+    $ \(Message bs) -> not (S.null bs) ==> signOpen pk2 (sign sk1 bs) == Nothing
 
     ]
diff --git a/tests/StreamProperties.hs b/tests/StreamProperties.hs
--- a/tests/StreamProperties.hs
+++ b/tests/StreamProperties.hs
@@ -4,15 +4,13 @@
   testStream
   ) where
 
-import Util
-
-import Crypto.Saltine.Core.Stream
-
-import qualified Data.ByteString as S
+import           Util
+import           Crypto.Saltine.Core.Stream
 
-import Test.Framework.Providers.QuickCheck2
-import Test.Framework
-import Test.QuickCheck
+import qualified Data.ByteString                      as S
+import           Test.Framework.Providers.QuickCheck2
+import           Test.Framework
+import           Test.QuickCheck
 
 testStream :: Test
 testStream = buildTest $ do
@@ -30,7 +28,5 @@
 
     testProperty "xor is involutive"
     $ \(Message bs) -> xor k n (xor k n bs) == bs
-    
+
     ]
-    
-       
diff --git a/tests/Util.hs b/tests/Util.hs
--- a/tests/Util.hs
+++ b/tests/Util.hs
@@ -1,19 +1,18 @@
 module Util where
 
-import Test.QuickCheck
-
-import Crypto.Saltine.Class
+import           Crypto.Saltine.Class
 
-import qualified Data.ByteString as S
+import           Control.Applicative
+import           Control.Monad           (replicateM)
+import qualified Data.ByteString       as S
 import qualified Data.ByteString.Char8 as S8
-import Control.Monad (replicateM)
+import           Data.Maybe              (fromMaybe)
+import           Test.QuickCheck
 
-import Control.Applicative
 
 perturb :: IsEncoding a => a -> a
-perturb a = case decode (S.reverse (encode a)) of
-  Just x -> x
-  Nothing -> error "Util.perturb"
+perturb a = fromMaybe (error "Util.perturb")
+                      (decode (S.reverse (encode a)))
 
 newtype ByteString32 = ByteString32 S.ByteString deriving (Show)
 
