1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI #-}
-- |An interface to symmetric cipher algorithms.
module OpenSSL.EVP.Cipher
( Cipher
, getCipherByName
, getCipherNames
, CryptoMode(..)
, cipher
, cipherBS
, cipherLBS
, cipherStrictLBS
)
where
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as L8
import Foreign
import Foreign.C
import OpenSSL.Objects
import OpenSSL.EVP.Internal
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid
#endif
foreign import capi unsafe "openssl/evp.h EVP_get_cipherbyname"
_get_cipherbyname :: CString -> IO (Ptr EVP_CIPHER)
-- |@'getCipherByName' name@ returns a symmetric cipher algorithm
-- whose name is @name@. If no algorithms are found, the result is
-- @Nothing@.
getCipherByName :: String -> IO (Maybe Cipher)
getCipherByName name
= withCString name $ \ namePtr ->
do ptr <- _get_cipherbyname namePtr
if ptr == nullPtr then
return Nothing
else
return $ Just $ Cipher ptr
-- |@'getCipherNames'@ returns a list of name of symmetric cipher
-- algorithms.
getCipherNames :: IO [String]
getCipherNames = getObjNames CipherMethodType True
{- encrypt/decrypt ----------------------------------------------------------- -}
-- | Encrypt a lazy bytestring in a strict manner. Does not leak the keys.
cipherStrictLBS :: Cipher -- ^ Cipher
-> B8.ByteString -- ^ Key
-> B8.ByteString -- ^ IV
-> CryptoMode -- ^ Encrypt\/Decrypt
-> L8.ByteString -- ^ Input
-> IO L8.ByteString
cipherStrictLBS c key iv mode input =
do ctx <- cipherInitBS c key iv mode
xs <- cipherUpdateBS ctx `mapM` L8.toChunks input
x <- cipherFinalBS ctx
return $ L8.fromChunks (xs `mappend` [x])
-- |@'cipher'@ lazilly encrypts or decrypts a stream of data. The
-- input string doesn't necessarily have to be finite.
cipher :: Cipher -- ^ algorithm to use
-> String -- ^ symmetric key
-> String -- ^ IV
-> CryptoMode -- ^ operation
-> String -- ^ An input string to encrypt\/decrypt. Note
-- that the string must not contain any letters
-- which aren't in the range of U+0000 -
-- U+00FF.
-> IO String -- ^ the result string
{-# DEPRECATED cipher "Use cipherBS, cipherLBS or cipherStrictLBS." #-}
cipher c key iv mode input
= fmap L8.unpack $ cipherLBS c (B8.pack key) (B8.pack iv) mode (L8.pack input)
-- |@'cipherBS'@ strictly encrypts or decrypts a chunk of data.
cipherBS :: Cipher -- ^ algorithm to use
-> B8.ByteString -- ^ symmetric key
-> B8.ByteString -- ^ IV
-> CryptoMode -- ^ operation
-> B8.ByteString -- ^ input string to encrypt\/decrypt
-> IO B8.ByteString -- ^ the result string
cipherBS c key iv mode input
= do ctx <- cipherInitBS c key iv mode
cipherStrictly ctx input
-- |@'cipherLBS'@ lazilly encrypts or decrypts a stream of data. The
-- input string doesn't necessarily have to be finite.
cipherLBS :: Cipher -- ^ algorithm to use
-> B8.ByteString -- ^ symmetric key
-> B8.ByteString -- ^ IV
-> CryptoMode -- ^ operation
-> L8.ByteString -- ^ input string to encrypt\/decrypt
-> IO L8.ByteString -- ^ the result string
cipherLBS c key iv mode input
= do ctx <- cipherInitBS c key iv mode
cipherLazily ctx input
|