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
deriveKeys :: Key256 -> [Key256]
deriveKeys mk =
[deriveKey mk (Block256 $ runPut $ mapM_ putWord64le [kid,0,0,0]) |
kid <- [0..]]
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