fastpbkdf2-0.1.0.0: src/Crypto/KDF/PBKDF2.hs
module Crypto.KDF.PBKDF2 (
fastpbkdf2_hmac_sha1
, fastpbkdf2_hmac_sha256
, fastpbkdf2_hmac_sha512
) where
import Data.ByteString
import Data.ByteString.Unsafe
import Data.Monoid
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr
import System.IO.Unsafe
foreign import ccall "fastpbkdf2_hmac_sha1" c_fastpbkdf2_hmac_sha1 :: Signature
foreign import ccall "fastpbkdf2_hmac_sha256" c_fastpbkdf2_hmac_sha256 :: Signature
foreign import ccall "fastpbkdf2_hmac_sha512" c_fastpbkdf2_hmac_sha512 :: Signature
type Signature = Ptr CChar -> CSize -> Ptr CChar -> CSize -> CInt -> Ptr CChar -> CSize -> IO ()
fastpbkdf2_fn :: Signature
-> ByteString
-- ^ The user key (e.g. a password)
-> ByteString
-- ^ The salt
-> Int
-- ^ The iteration count
-> Int
-- ^ The length (in bytes) of the output
-> ByteString
fastpbkdf2_fn fn password salt iterations keyLen = unsafeDupablePerformIO $ do
withPositive (iterations, keyLen) $ do
let outSize = CSize (fromIntegral keyLen)
outForeignPtr <- mallocForeignPtrBytes keyLen
withForeignPtr outForeignPtr $ \ptrOut -> do
unsafeUseAsCStringLen password $ \(passwordPtr, passwordSizeInt) -> do
unsafeUseAsCStringLen salt $ \(saltPtr, saltSizeInt) -> do
let passwordSize = CSize (fromIntegral passwordSizeInt)
let saltSize = CSize (fromIntegral saltSizeInt)
let iters = CInt (fromIntegral iterations)
fn passwordPtr passwordSize saltPtr saltSize iters ptrOut outSize
unsafePackCStringLen (ptrOut, keyLen)
{-# NOINLINE fastpbkdf2_fn #-}
withPositive :: (Int, Int) -> IO a -> IO a
withPositive (iter, keyLen) action
| iter <= 0 = error $ "fastpbkdf2: iteration count must be > 0 (it was " <> show iter <> ")"
| keyLen <= 0 = error $ "fastpbkdf2: key length must be > 0 (it was " <> show keyLen <> ")"
| otherwise = action
--------------------------------------------------------------------------------
fastpbkdf2_hmac_sha1 :: ByteString
-- ^ The user key (e.g. a password)
-> ByteString
-- ^ The salt
-> Int
-- ^ The iteration count
-> Int
-- ^ The length (in bytes) of the output
-> ByteString
fastpbkdf2_hmac_sha1 = fastpbkdf2_fn c_fastpbkdf2_hmac_sha1
{-# INLINE fastpbkdf2_hmac_sha1 #-}
--------------------------------------------------------------------------------
fastpbkdf2_hmac_sha256 :: ByteString
-- ^ The user key (e.g. a password)
-> ByteString
-- ^ The salt
-> Int
-- ^ The iteration count
-> Int
-- ^ The length (in bytes) of the output
-> ByteString
fastpbkdf2_hmac_sha256 = fastpbkdf2_fn c_fastpbkdf2_hmac_sha256
{-# INLINE fastpbkdf2_hmac_sha256 #-}
--------------------------------------------------------------------------------
fastpbkdf2_hmac_sha512 :: ByteString
-- ^ The user key (e.g. a password)
-> ByteString
-- ^ The salt
-> Int
-- ^ The iteration count
-> Int
-- ^ The length (in bytes) of the output
-> ByteString
fastpbkdf2_hmac_sha512 = fastpbkdf2_fn c_fastpbkdf2_hmac_sha512
{-# INLINE fastpbkdf2_hmac_sha512 #-}