module OpenSSL.EVP.Digest
( Digest
, getDigestByName
, getDigestNames
, digest
, 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 Foreign.C.String (CString, withCString)
import Foreign.C.Types (CChar(..), CInt(..), CSize(..), CUInt(..))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (allocaArray)
import Foreign.Ptr (Ptr, castPtr, nullPtr)
import Foreign.Storable (peek)
import OpenSSL.EVP.Internal
import OpenSSL.Objects
import System.IO.Unsafe (unsafePerformIO)
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
= B8.unpack $ digestLBS md $ L8.pack input
digestBS :: Digest -> B8.ByteString -> B8.ByteString
digestBS md input
= unsafePerformIO $ digestStrictly md input >>= digestFinalBS
digestLBS :: Digest -> L8.ByteString -> B8.ByteString
digestLBS md input
= unsafePerformIO $ digestLazily md input >>= digestFinalBS
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