diff --git a/Crypto/Threefish.hs b/Crypto/Threefish.hs
--- a/Crypto/Threefish.hs
+++ b/Crypto/Threefish.hs
@@ -2,8 +2,8 @@
 -- | 256 and 512 bit variants of the Threefish block cipher used as the
 --   foundation of the Skein hash function.
 module Crypto.Threefish (  
-    Block256 (..), Threefish256, Key256,
-    Block512 (..), Threefish512, Key512,
+    Block256, Threefish256, Key256,
+    Block512, Threefish512, Key512,
     Tweak (..), parseHex, readHex, defaultTweak,
     Threefish (..)
 ) where
@@ -11,6 +11,7 @@
 import Crypto.Threefish.Threefish512 as TF512
 import Crypto.Threefish.Common as Common
 import Data.Serialize
+import qualified Data.ByteString as BS
 
 class Serialize a => Threefish a b | a -> b where
   -- | Create a Threefish key using a custom tweak value.
@@ -19,13 +20,24 @@
   threefishEncrypt :: a -> Tweak -> a -> a
   -- | Decrypt a block using the given key and tweak value.
   threefishDecrypt :: a -> Tweak -> a -> a
+  -- | Create an appropriately sized block.
+  toBlock :: BS.ByteString -> Maybe a
+  -- | Extract the contents of a block.
+  fromBlock :: a -> BS.ByteString
 
 instance Threefish Block256 Threefish256 where
   threefishKey = Threefish256
   threefishEncrypt = encrypt256
   threefishDecrypt = decrypt256
+  toBlock bs = if BS.length bs /= 32 then Nothing else Just (Block256 bs)
+  fromBlock (Block256 bs) = bs
 
 instance Threefish Block512 Threefish512 where
   threefishKey = Threefish512
   threefishEncrypt = encrypt512
   threefishDecrypt = decrypt512
+  toBlock bs =
+    case decode bs of
+      Right block -> Just block
+      _           -> Nothing
+  fromBlock = encode
diff --git a/Crypto/Threefish/Authenticated.hs b/Crypto/Threefish/Authenticated.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Threefish/Authenticated.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE OverloadedStrings #-}
+-- | Authenticated encryption using Skein for PRNG, KDF, stream cipher and MAC.
+module Crypto.Threefish.Authenticated (
+    DecryptFailure (..), Encrypted, Plaintext, Block256, Nonce256,
+    encrypt, decrypt, encrypt', decrypt', generateNonce, toBlock, fromBlock
+  ) where
+import Crypto.Threefish
+import Crypto.Threefish.Threefish256 (Block256(..))
+import Crypto.Threefish.Skein
+import Crypto.Threefish.Skein.KDF hiding (deriveKeys)
+import qualified Crypto.Threefish.Skein.StreamCipher as SC
+import Crypto.Threefish.Random
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
+import System.IO.Unsafe
+import Data.IORef
+import Data.Serialize
+import Control.Monad
+
+{-# NOINLINE prng #-}
+prng :: IORef SkeinGen
+prng = unsafePerformIO $ newSkeinGen >>= newIORef
+
+-- | Generate a 256 bit nonce using the Skein PRNG.
+generateNonce :: IO Nonce256
+generateNonce =
+    Block256 `fmap` atomicModifyIORef' prng (pflip . randomBytes 32)
+  where
+    pflip (a, b) = (b, a)
+
+type MAC256 = Block256
+type Plaintext = BSL.ByteString
+
+data DecryptFailure = BadMAC | NoDecode String deriving Show
+
+-- | An encrypt-then-MACed value. The binary format is as follows:
+--   Bytes    What
+--   0-31     256 bit nonce
+--   32-63    256 bit Skein-MAC
+--   64-71    Length of cryptotext as a 64 bit little endian word.
+--   71-      Cryptotext
+data Encrypted a = Encrypted {
+    encNonce :: Nonce256, 
+    encMAC   :: MAC256, 
+    encData  :: BSL.ByteString
+  } deriving Show
+
+instance Serialize (Encrypted a) where
+  put (Encrypted (Block256 nonce) (Block256 mac) cryptotext) = do
+    putByteString nonce
+    putByteString mac
+    putWord64le (fromIntegral $ BSL.length cryptotext)
+    putLazyByteString cryptotext
+  get = do
+    nonce <- getByteString 32
+    mac <- getByteString 32
+    len <- getWord64le
+    cryptotext <- getLazyByteString (fromIntegral len)
+    return $! Encrypted (Block256 nonce) (Block256 mac) cryptotext
+
+deriveKeys :: Key256 -> (Key256, Key256)
+deriveKeys k = (deriveKey k (Block256 $ BS.append "crypt" (BS.replicate 27 0)),
+                deriveKey k (Block256 $ BS.append "mac" (BS.replicate 29 0)))
+
+-- | Encrypt-then-MAC a message given a key and a nonce. Note that using the
+--   same nonce more than once for a given key will completely destroy
+--   security.
+encrypt' :: Key256 -> Nonce256 -> Plaintext -> Encrypted a
+encrypt' k n plaintext =
+    Encrypted n mac cryptotext
+  where
+    (cryptKey, macKey) = deriveKeys k
+    cryptotext = SC.encrypt cryptKey n plaintext
+    mac = skeinMAC macKey cryptotext
+
+-- | Verify and decrypt a message.
+decrypt' :: Key256 -> Encrypted a -> Either DecryptFailure Plaintext
+decrypt' k (Encrypted n mac cryptotext) = do
+    when (mac' /= mac) $ Left BadMAC
+    return $! SC.decrypt cryptKey n cryptotext
+  where
+    (cryptKey, macKey) = deriveKeys k
+    mac' = skeinMAC macKey cryptotext
+
+-- | Encrypt-then-MAC any serializable value.
+--   The 256 bit nonce is generated using a Skein-based PRNG seeded from the
+--   system's entropy pool. This means that two successive calls to encrypt
+--   will not yield the exact same output; however, the identity
+--   forall k, x. Right x == decrypt k (encrypt k x)
+--   will always hold.
+--
+--   The subkeys for encryption and MAC are generated by applying Skein-KDF
+--   to the master key, with the key identifiers "crypt" and "mac"
+--   respectively, zero padded at the end until 32 bytes.
+encrypt :: Serialize a => Key256 -> a -> Encrypted a
+encrypt k x = unsafePerformIO $ do
+  nonce <- generateNonce
+  return $! encrypt' k nonce (runPutLazy (put x))
+
+-- | Decrypt and decode a message. Will fail if there is a MAC mismatch or if
+--   the message can't be decoded into the given data type.
+decrypt :: Serialize a => Key256 -> Encrypted a -> Either DecryptFailure a
+decrypt k enc = do
+  plaintext <- decrypt' k enc
+  case runGetLazy get plaintext of
+    Right x  -> return x
+    Left err -> Left (NoDecode err)
diff --git a/Crypto/Threefish/Random.hs b/Crypto/Threefish/Random.hs
--- a/Crypto/Threefish/Random.hs
+++ b/Crypto/Threefish/Random.hs
@@ -1,17 +1,22 @@
 -- | Skein 256 as a PRNG.
 module Crypto.Threefish.Random (
-    SkeinGen, Block256 (..), Random (..), RandomGen (..),
-    newSkeinGen, mkSkeinGen, mkSkeinGenEx, randomBytes
+    SkeinGen, Block256, Random (..), RandomGen (..),
+    newSkeinGen, mkSkeinGen, mkSkeinGenEx, randomBytes, reseedSkeinGen,
+    toBlock, fromBlock
   ) where
 import Crypto.Threefish.Skein
+import Crypto.Threefish.Threefish256
 import System.Random
 import System.Entropy
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
 import Data.ByteString.Unsafe
 import System.IO.Unsafe
 import Foreign.Storable (sizeOf, peek)
 import Foreign.Ptr (castPtr)
 import Data.Serialize
+import Crypto.Random
+import Data.Tagged
 
 emptyKey :: Key256
 emptyKey = Block256 BS.empty
@@ -50,11 +55,20 @@
 --   across splits.
 mkSkeinGenEx :: Int -> Block256 -> SkeinGen
 mkSkeinGenEx poolsize (Block256 seed) = SkeinGen {
-    sgState    = skein (BS.replicate 32 0 `BS.append` seed),
+    sgState    = skein $ BSL.fromStrict (BS.replicate 32 0 `BS.append` seed),
     sgPool     = BS.empty,
     sgPoolSize = poolsize
   }
 
+-- | Reseed a Skein PRNG.
+reseedSkeinGen :: Block256 -> SkeinGen -> SkeinGen
+reseedSkeinGen (Block256 seed) (SkeinGen (Block256 state) _ poolsize) =
+  SkeinGen {
+    sgState    = skein $ BSL.fromStrict (state `BS.append` seed),
+    sgPool     = BS.empty,
+    sgPoolSize = poolsize
+  }
+
 -- | Generate n random bytes using the given generator.
 randomBytes :: Int -> SkeinGen -> (BS.ByteString, SkeinGen)
 randomBytes nbytes (SkeinGen (Block256 state) pool poolsize)
@@ -65,7 +79,26 @@
       (BS.append pool out, SkeinGen (Block256 state') pool' poolsize)
   where
     -- Use all of the output to avoid making unnecessary calls
-    nbytes' = 32 + max (nbytes + (32-(nbytes`rem`32))) poolsize
-    bytes = hash256 nbytes' emptyKey emptyKey state
+    nbytes' = fromIntegral $ 32 + max (nbytes + (32-(nbytes`rem`32))) poolsize
+    bytes = hash256 nbytes' emptyKey (BSL.fromStrict state)
     (state', buffer) = BS.splitAt 32 bytes
     (out, pool') = BS.splitAt (nbytes - BS.length pool) buffer
+
+instance CryptoRandomGen SkeinGen where
+  newGen seed =
+    case BS.length seed of
+      n | n >= 32 ->
+          Right $ mkSkeinGenEx ps (Block256 $ BS.take 32 seed)
+        | otherwise ->
+          Left NotEnoughEntropy
+    where ps = defaultSkeinGenPoolSize
+  genSeedLength = Tagged 32
+  genBytes n g = Right $ randomBytes n g
+  reseedInfo = const Never
+  reseedPeriod = const Never
+  reseed seed g =
+    case BS.length seed of
+      n | n >= 32 ->
+          Right $ reseedSkeinGen (Block256 $ BS.take 32 seed) g
+        | otherwise ->
+          Left NotEnoughEntropy
diff --git a/Crypto/Threefish/Skein.hs b/Crypto/Threefish/Skein.hs
--- a/Crypto/Threefish/Skein.hs
+++ b/Crypto/Threefish/Skein.hs
@@ -1,69 +1,86 @@
-{-# LANGUAGE BangPatterns, OverloadedStrings, ForeignFunctionInterface #-}
+{-# LANGUAGE BangPatterns, OverloadedStrings, MultiParamTypeClasses #-}
 -- | 256 and 512 bit Skein. Supports "normal" hashing and Skein-MAC.
 module Crypto.Threefish.Skein (
-    Skein (..), Block256 (..), Block512 (..), Key256, Key512, Nonce256,
+    Skein (..), Threefish (..), Block256, Block512, Key256, Key512, Nonce256,
     hash256, hash512
   ) where
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
 import Crypto.Threefish.Threefish256
 import Crypto.Threefish.Threefish512
 import Crypto.Threefish.UBI
+import Crypto.Threefish
+import Crypto.Threefish.Skein.Internal
 import Data.Bits
 import Data.Serialize
 import Data.Word
 import Data.ByteString.Unsafe
 import Foreign.Ptr
 import Foreign.ForeignPtr
+import Foreign.Marshal.Alloc
 import System.IO.Unsafe
 
-foreign import ccall "hash256" c_hash256 :: Ptr Word64 -- ^ Key (nullPtr for none)
-                                         -> Ptr Word64 -- ^ Nonce (nullPtr for none)
-                                         -> Word64     -- ^ Message length
-                                         -> Ptr Word64 -- ^ Message
-                                         -> Int        -- ^ Size of output, in bytes
-                                         -> Ptr Word64 -- ^ Output blocks pointer
-                                         -> IO ()
-
 class Skein a where
   -- | Calculate the Skein-MAC of a message.
-  skeinMAC :: a -> BS.ByteString -> a
+  skeinMAC :: a -> BSL.ByteString -> a
   -- | Calculate the Skein checksum of a message.
-  skein :: BS.ByteString -> a
+  skein :: BSL.ByteString -> a
 
 type Nonce256 = Block256
 
--- | Hash a message using a particular key. For normal hashing, use an empty
---   ByteString; for Skein-MAC, use the MAC key.
-hash256 :: Int -> Key256 -> Nonce256 -> BS.ByteString -> BS.ByteString
-hash256 outlen (Block256 key) (Block256 nonce) !msg =
-    unsafePerformIO $
-      withKey $ \k -> do
-        withNonce $ \n -> do
-          unsafeUseAsCString msg $ \b -> do
-            out <- mallocForeignPtrArray (outblocks*32)
-            withForeignPtr out $ \out' -> do
-              c_hash256 k n len (castPtr b) outlen out'
-              BS.packCStringLen (castPtr out', outlen)
+init256 :: Key256 -> Word64 -> Skein256Ctx
+init256 (Block256 k) outlen =
+    unsafePerformIO $ do
+      c <- mallocForeignPtrBytes 64
+      withForeignPtr c $ \ctx -> do
+        withKey $ \key -> do
+          skein256_init ctx (castPtr key) (outlen*8)
+      return (Skein256Ctx c)
   where
+    withKey f | BS.length k == 32 = unsafeUseAsCString k (f . castPtr)
+              | otherwise         = f nullPtr
+
+update256 :: Skein256Ctx -> Int -> BSL.ByteString -> BS.ByteString
+update256 (Skein256Ctx c) outlen bytes =
+    unsafePerformIO $ withForeignPtr c $ go 1 bytes
+  where
     outblocks =
       case outlen `quotRem` 32 of
         (blocks, 0) -> blocks
         (blocks, _) -> blocks+1
-    !len = fromIntegral $ BS.length msg
-    withKey f | BS.length key == 32 = unsafeUseAsCString key (f . castPtr)
-                | otherwise         = f nullPtr
-    withNonce f | BS.length nonce == 32 = unsafeUseAsCString nonce (f . castPtr)
-                | otherwise             = f nullPtr
+    !msgtype = type2int Message
+    go !first !msg !ctx = do
+      case BSL.splitAt 16384 msg of
+        (chunk, rest)
+          | BSL.null chunk ->
+            allocaBytes (outblocks*32) $ \ptr -> do
+              skein256_output ctx 0 (outblocks-1) ptr
+              BS.packCStringLen (castPtr ptr, outlen)
+          | otherwise -> do
+              let !chunk' =
+                    BSL.toStrict chunk
+                  (!lst, !len) =
+                    if BSL.null rest
+                      then (2, fromIntegral $ BS.length chunk')
+                      else (0, 16384)
+              unsafeUseAsCString chunk' $ \ptr -> do
+                skein256_update ctx (first .|. lst) msgtype len (castPtr ptr)
+              go 0 rest ctx
 
+hash256 :: Word64 -> Key256 -> BSL.ByteString -> BS.ByteString
+hash256 outlen k bs =
+    case init256 k outlen of
+      ctx -> update256 ctx (fromIntegral outlen) bs
+
 {-# INLINE skein256 #-}
 -- | Hash a message using 256 bit Skein.
-skein256 :: BS.ByteString -> Block256
-skein256 = Block256 . hash256 32 (Block256 "") (Block256 "")
+skein256 :: BSL.ByteString -> Block256
+skein256 = Block256 . hash256 32 (Block256 "")
 
 {-# INLINE skeinMAC256 #-}
 -- | Create a 256 bit Skein-MAC.
-skeinMAC256 :: Key256 -> BS.ByteString -> Block256
-skeinMAC256 key = Block256 . hash256 32 key (Block256 "")
+skeinMAC256 :: Key256 -> BSL.ByteString -> Block256
+skeinMAC256 key = Block256 . hash256 32 key
 
 instance Skein Block256 where
   skeinMAC = skeinMAC256
@@ -103,16 +120,16 @@
 
 -- | Hash a message using a particular key. For normal hashing, use all zeroes;
 --   for Skein-MAC, use the MAC key.
-hash512 :: Key512 -> BS.ByteString -> Block512
+hash512 :: Key512 -> BSL.ByteString -> Block512
 hash512 !firstkey !bs =
-    case flip runGet bs' $ go len (init512 firstkey) (newTweak Message) of
+    case flip runGetLazy bs' $ go len (init512 firstkey) (newTweak Message) of
       Right x -> x
       Left _  -> error "hash512 failed to get output bytes - impossible!"
   where
-    !len = BS.length bs
+    !len = BSL.length bs
     !lastLen = case len `rem` 64 of 0 -> 64 ; n -> n
     !lastLenW64 = fromIntegral lastLen
-    !bs' = BS.append bs (BS.replicate (64-lastLen) 0)
+    !bs' = BSL.append bs (BSL.replicate (64-fromIntegral lastLen) 0)
     go !n !key !tweak
       | n > 64 = do
         block <- get
@@ -128,12 +145,12 @@
 
 {-# INLINE skein512 #-}
 -- | Hash a message using 512 bit Skein.
-skein512 :: BS.ByteString -> Block512
+skein512 :: BSL.ByteString -> Block512
 skein512 = hash512 zero512
 
 {-# INLINE skeinMAC512 #-}
 -- | Create a 512 bit Skein-MAC.
-skeinMAC512 :: Key512 -> BS.ByteString -> Block512
+skeinMAC512 :: Key512 -> BSL.ByteString -> Block512
 skeinMAC512 =
   hash512 . fst . processBlock512 64 zero512 (setLast True $ newTweak Key)
 
diff --git a/Crypto/Threefish/Skein/KDF.hs b/Crypto/Threefish/Skein/KDF.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Threefish/Skein/KDF.hs
@@ -0,0 +1,34 @@
+-- | Skein as a key derivation function.
+module Crypto.Threefish.Skein.KDF (deriveKey, deriveKeys) where
+import Crypto.Threefish.Skein.Internal
+import Crypto.Threefish.Skein
+import Crypto.Threefish.UBI
+import Crypto.Threefish.Threefish256
+import Data.Serialize
+import qualified Data.ByteString as BS
+import Data.ByteString.Unsafe
+import System.IO.Unsafe
+import Foreign.Marshal.Alloc
+import Foreign.Ptr
+
+-- | Derive up to 2^64 keys from a master key.
+--   The key identifiers will be 0, 1, ... 2^64-1.
+deriveKeys :: Key256 -> [Key256]
+deriveKeys mk =
+  [deriveKey mk (Block256 $ runPut $ mapM_ putWord64le [kid,0,0,0]) |
+   kid <- [0..]]
+
+-- | Derive a key from a master key using a custom key identifier.
+deriveKey :: Key256 -> Block256 -> Key256
+deriveKey (Block256 mk) (Block256 kid) =
+    unsafePerformIO $ do
+      allocaBytes 64 $ \ctx -> do
+        allocaBytes 32 $ \outkey -> do
+          unsafeUseAsCString mk $ \masterkey -> do
+            unsafeUseAsCString kid $ \keyid -> do
+              skein256_init ctx (castPtr masterkey) 256
+              skein256_update ctx 3 (type2int KeyIdentifier) l (castPtr keyid)
+              skein256_output ctx 0 0 outkey
+              Block256 `fmap` BS.packCStringLen (castPtr outkey, 32)
+  where
+    l = fromIntegral $ BS.length kid
diff --git a/Crypto/Threefish/Skein/StreamCipher.hs b/Crypto/Threefish/Skein/StreamCipher.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Threefish/Skein/StreamCipher.hs
@@ -0,0 +1,67 @@
+-- | 256 bit Skein as a stream cipher, as specified in the Skein 1.3 paper.
+module Crypto.Threefish.Skein.StreamCipher (
+    Key256, Nonce256, Block256,
+    encrypt, decrypt, toBlock, fromBlock
+  ) where
+import Crypto.Threefish.Skein (Nonce256)
+import Crypto.Threefish.UBI
+import Crypto.Threefish.Threefish256
+import Crypto.Threefish
+import Crypto.Threefish.Skein.Internal
+import Data.ByteString.Unsafe
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
+import Foreign.ForeignPtr
+import Foreign.Ptr
+import Foreign.Marshal.Alloc
+import System.IO.Unsafe
+import Data.Bits (xor)
+
+init256 :: Key256 -> Nonce256 -> Skein256Ctx
+init256 (Block256 k) (Block256 n) =
+    unsafePerformIO $ do
+      c <- mallocForeignPtrBytes 64
+      withForeignPtr c $ \ctx -> do
+        unsafeUseAsCString k $ \key -> do
+          unsafeUseAsCString n $ \nonce -> do
+            skein256_init ctx (castPtr key) 0xffffffffffffffff
+            skein256_update ctx 3 (type2int Nonce) len (castPtr nonce)
+      return (Skein256Ctx c)
+  where
+    len = fromIntegral $ BS.length n
+
+stream256 :: Skein256Ctx -> [BS.ByteString]
+stream256 (Skein256Ctx c) =
+    unsafePerformIO $ go 0
+  where
+    go n = unsafeInterleaveIO $ do
+      bs <- withForeignPtr c $ \ctx -> do
+        allocaBytes 256 $ \ptr -> do
+          skein256_output ctx n (n+8) ptr
+          BS.packCStringLen (castPtr ptr, 256)
+      bss <- go (n+8)
+      return $ bs : bss
+
+keystream256 :: Key256 -> Nonce256 -> [BS.ByteString]
+keystream256 k n = stream256 (init256 k n)
+
+-- | Encrypt a lazy ByteString using 256 bit Skein as a stream cipher.
+encrypt :: Key256 -> Nonce256 -> BSL.ByteString -> BSL.ByteString
+encrypt k n plaintext =
+    BSL.fromChunks $ go (keystream256 k n) plaintext
+  where
+    go (ks:kss) msg = unsafePerformIO . unsafeInterleaveIO $ do
+      case BSL.splitAt 256 msg of
+        (chunk, rest)
+          | BSL.null chunk ->
+            return []
+          | otherwise ->
+            let chunk' = BSL.toStrict chunk
+            in  return $ (BS.pack $ BS.zipWith xor ks chunk') : go kss rest
+    go _ _ =
+      error "The key stream is infinite, so this will never happen."
+
+-- | Encryption and decryption are the same operation for a stream cipher, but
+--   we may want to have a function called encrypt for clarity.
+decrypt :: Key256 -> Nonce256 -> BSL.ByteString -> BSL.ByteString
+decrypt = encrypt
diff --git a/Crypto/Threefish/UBI.hs b/Crypto/Threefish/UBI.hs
--- a/Crypto/Threefish/UBI.hs
+++ b/Crypto/Threefish/UBI.hs
@@ -24,6 +24,16 @@
 type2w64 Message         = 48
 type2w64 Output          = 63
 
+type2int :: BlockType -> Int
+type2int Key             = 0
+type2int Config          = 4
+type2int Personalization = 8
+type2int PublicKey       = 12
+type2int KeyIdentifier   = 16
+type2int Nonce           = 20
+type2int Message         = 48
+type2int Output          = 63
+
 {-# INLINE newTweak #-}
 newTweak :: BlockType -> Tweak
 newTweak t = setType t $ setFirst True $ Tweak 0 0
diff --git a/cbits/skein256.c b/cbits/skein256.c
--- a/cbits/skein256.c
+++ b/cbits/skein256.c
@@ -1,8 +1,8 @@
 #include "threefish.h"
 #include <string.h>
 
-void skein256_init(skein_t* ctx, W64* key, int outlen) {
-  W64 config[4] = {0x0000000133414853, outlen*8, 0, 0};
+void skein256_init(skein_t* ctx, W64* key, W64 outlen) {
+  W64 config[4] = {0x0000000133414853, outlen, 0, 0};
   static W64 zeroes[4] = {0,0,0,0};
 
   /* Set up key if needed */
@@ -83,23 +83,4 @@
     out += 4;
     ++buf[0];
   }
-}
-
-void hash256(W64* key, W64* nonce, W64 len, W64* data, int outlen, W64* out) {
-  skein_t ctx;
-
-  skein256_init(&ctx, key, outlen);
-
-  /* Process nonce, if available; must be 32 bytes */
-  if(nonce != NULL) {
-    skein256_update(&ctx, 3, T_NONCE, 32, nonce);
-  }
-
-  skein256_update(&ctx, 3, T_MSG, len, data);
-  if(outlen % 32 == 0) {
-    outlen = outlen / 32;
-  } else {
-    outlen = (outlen / 32) + 1;
-  }
-  skein256_output(&ctx, 0, outlen, out);
 }
diff --git a/threefish.cabal b/threefish.cabal
--- a/threefish.cabal
+++ b/threefish.cabal
@@ -1,7 +1,7 @@
 name:                threefish
-version:             0.1
+version:             0.2
 synopsis:            The Threefish block cipher and the Skein hash function for Haskell.
-description:         Implements 256 and 512 bit variants of Threefish and Skein. Skein is usable as a "normal" hash function as well as in Skein-MAC mode and as a cryptographically secure PRNG, as specified in the Skein 1.3 paper.
+description:         Implements 256 and 512 bit variants of Threefish and Skein. Skein is usable as a "normal" hash function as well as in Skein-MAC, as a cryptographically secure PRNG, as a stream cipher and as a key derivation function, all implemented according to the specifications of the Skein 1.3 paper.
 homepage:            http://github.com/valderman/threefish
 license:             BSD3
 license-file:        LICENSE
@@ -13,11 +13,18 @@
 -- extra-source-files:  
 cabal-version:       >=1.10
 
+source-repository head
+    type:       git
+    location:   https://github.com/valderman/threefish.git
+
 library
   exposed-modules:
     Crypto.Threefish,
+    Crypto.Threefish.Authenticated,
     Crypto.Threefish.Random,
-    Crypto.Threefish.Skein
+    Crypto.Threefish.Skein,
+    Crypto.Threefish.Skein.KDF,
+    Crypto.Threefish.Skein.StreamCipher
   other-modules:
     Crypto.Threefish.Common,
     Crypto.Threefish.Mix,
@@ -30,7 +37,7 @@
     FunctionalDependencies
   build-depends:
     base >=4.6 && <5,
-    bytestring >=0.10,
+    bytestring >=0.10.2.0,
     cereal >=0.3,
     array >=0.4,
     crypto-api >=0.12,
