summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonEkblad <>2013-09-28 14:45:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2013-09-28 14:45:00 (GMT)
commitb3f4f9ef100be27e62ab6e4e44f5336451340fbd (patch)
tree4c436c0374e8b27b02aad22de0b939987a39806b
parent2ee4c06535b40fdc2db306e5ac74c037ec3e32fb (diff)
version 0.2HEAD0.2master
-rw-r--r--Crypto/Threefish.hs16
-rw-r--r--Crypto/Threefish/Authenticated.hs107
-rw-r--r--Crypto/Threefish/Random.hs43
-rw-r--r--Crypto/Threefish/Skein.hs95
-rw-r--r--Crypto/Threefish/Skein/KDF.hs34
-rw-r--r--Crypto/Threefish/Skein/StreamCipher.hs67
-rw-r--r--Crypto/Threefish/UBI.hs10
-rw-r--r--cbits/skein256.c23
-rw-r--r--threefish.cabal15
9 files changed, 339 insertions, 71 deletions
diff --git a/Crypto/Threefish.hs b/Crypto/Threefish.hs
index 41638bd..ee7670a 100644
--- 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.Threefish256 as TF256
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 @@ class Serialize a => Threefish a b | a -> b where
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
index 0000000..63608b7
--- /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
index cd4b179..dea58cc 100644
--- 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,7 +55,16 @@ mkSkeinGen = mkSkeinGenEx defaultSkeinGenPoolSize . Block256 . encode
-- 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
}
@@ -65,7 +79,26 @@ randomBytes nbytes (SkeinGen (Block256 state) pool poolsize)
(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
index 1cdadf3..aaac98b 100644
--- 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 @@ processBlock512 !len !key !tweak !block =
-- | 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 @@ hash512 !firstkey !bs =
{-# 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
index 0000000..f07eebd
--- /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
index 0000000..c37f2ca
--- /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
index 651a5d5..7e2be56 100644
--- a/Crypto/Threefish/UBI.hs
+++ b/Crypto/Threefish/UBI.hs
@@ -24,6 +24,16 @@ type2w64 Nonce = 20
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
index 838fbb8..7a20b6c 100644
--- 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 */
@@ -84,22 +84,3 @@ void skein256_output(skein_t* ctx, int from, int to, W64* out) {
++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
index 31b1d29..e4359a2 100644
--- 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 @@ build-type: Simple
-- 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 @@ library
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,