module OpenSSL.EVP.Digest
( Digest
, getDigestByName
, getDigestNames
, digest
, digestBS
, digestBS'
, digestLBS
, hmacBS
, pkcs5_pbkdf2_hmac_sha1
)
where
import Data.ByteString.Internal (create)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as L8
import Control.Applicative ((<$>))
import Foreign
import Foreign.C
import OpenSSL.EVP.Internal
import OpenSSL.Objects
foreign import ccall unsafe "EVP_get_digestbyname"
_get_digestbyname :: CString -> IO (Ptr EVP_MD)
getDigestByName :: String -> IO (Maybe Digest)
getDigestByName name
= withCString name $ \ namePtr ->
do ptr <- _get_digestbyname namePtr
if ptr == nullPtr then
return Nothing
else
return $ Just $ Digest ptr
getDigestNames :: IO [String]
getDigestNames = getObjNames MDMethodType True
digest :: Digest -> String -> String
digest md input
= digestLBS md $ L8.pack input
digestBS :: Digest -> B8.ByteString -> String
digestBS md input
= unsafePerformIO $ digestStrictly md input >>= digestFinal
digestBS' :: Digest -> B8.ByteString -> B8.ByteString
digestBS' md input
= unsafePerformIO $ digestStrictly md input >>= digestFinalBS
digestLBS :: Digest -> L8.ByteString -> String
digestLBS md input
= unsafePerformIO $ digestLazily md input >>= digestFinal
foreign import ccall unsafe "HMAC"
_HMAC :: Ptr EVP_MD -> Ptr CChar -> CInt -> Ptr CChar -> CSize
-> Ptr CChar -> Ptr CUInt -> IO ()
hmacBS :: Digest
-> B8.ByteString
-> B8.ByteString
-> B8.ByteString
hmacBS (Digest md) key input =
unsafePerformIO $
allocaArray (64) $ \bufPtr ->
alloca $ \bufLenPtr ->
unsafeUseAsCStringLen key $ \(keydata, keylen) ->
unsafeUseAsCStringLen input $ \(inputdata, inputlen) -> do
_HMAC md
keydata (fromIntegral keylen) inputdata (fromIntegral inputlen)
bufPtr bufLenPtr
bufLen <- fromIntegral <$> peek bufLenPtr
B8.packCStringLen (bufPtr, bufLen)
pkcs5_pbkdf2_hmac_sha1 :: B8.ByteString
-> B8.ByteString
-> Int
-> Int
-> B8.ByteString
pkcs5_pbkdf2_hmac_sha1 pass salt iter dkeylen =
unsafePerformIO $
unsafeUseAsCStringLen pass $ \(passdata, passlen) ->
unsafeUseAsCStringLen salt $ \(saltdata, saltlen) ->
create dkeylen $ \dkeydata ->
_PKCS5_PBKDF2_HMAC_SHA1
passdata (fromIntegral passlen)
saltdata (fromIntegral saltlen)
(fromIntegral iter) (fromIntegral dkeylen) (castPtr dkeydata)
>> return ()
foreign import ccall unsafe "PKCS5_PBKDF2_HMAC_SHA1"
_PKCS5_PBKDF2_HMAC_SHA1 :: Ptr CChar -> CInt
-> Ptr CChar -> CInt
-> CInt -> CInt -> Ptr CChar
-> IO CInt