module Crypto.Gpgme.Crypto (
encrypt
, encryptSign
, encrypt'
, encryptSign'
, decrypt
, decrypt'
, decryptVerify
, decryptVerify'
) where
import Bindings.Gpgme
import qualified Data.ByteString as BS
import Foreign
import GHC.Ptr
import Crypto.Gpgme.Ctx
import Crypto.Gpgme.Internal
import Crypto.Gpgme.Key
import Crypto.Gpgme.Types
locale :: String
locale = "C"
encrypt' :: String -> Fpr -> Plain -> IO (Either String Encrypted)
encrypt' = encryptIntern' encrypt
encryptSign' :: String -> Fpr -> Plain -> IO (Either String Encrypted)
encryptSign' = encryptIntern' encryptSign
encryptIntern' :: (Ctx -> [Key] -> Flag -> Plain
-> IO (Either [InvalidKey] Encrypted)
) -> String -> Fpr -> Plain -> IO (Either String Encrypted)
encryptIntern' encrFun gpgDir recFpr plain =
withCtx gpgDir locale OpenPGP $ \ctx ->
do mbRes <- withKey ctx recFpr NoSecret $ \pubKey ->
encrFun ctx [pubKey] NoFlag plain
return $ mapErr mbRes
where mapErr Nothing = Left $ "no such key: " ++ show recFpr
mapErr (Just (Left err)) = Left (show err)
mapErr (Just (Right res)) = Right res
encrypt :: Ctx -> [Key] -> Flag -> Plain -> IO (Either [InvalidKey] Encrypted)
encrypt = encryptIntern c'gpgme_op_encrypt
encryptSign :: Ctx -> [Key] -> Flag -> Plain -> IO (Either [InvalidKey] Encrypted)
encryptSign = encryptIntern c'gpgme_op_encrypt_sign
encryptIntern :: (C'gpgme_ctx_t
-> GHC.Ptr.Ptr C'gpgme_key_t
-> C'gpgme_encrypt_flags_t
-> C'gpgme_data_t
-> C'gpgme_data_t
-> IO C'gpgme_error_t
)
-> Ctx
-> [Key]
-> Flag
-> Plain
-> IO (Either [InvalidKey] Encrypted)
encryptIntern enc_op (Ctx ctxPtr _) recPtrs flag plain = do
plainBufPtr <- malloc
BS.useAsCString plain $ \bs -> do
let copyData = 1
let plainlen = fromIntegral (BS.length plain)
ret <- c'gpgme_data_new_from_mem plainBufPtr bs plainlen copyData
checkError "data_new_from_mem" ret
plainBuf <- peek plainBufPtr
resultBufPtr <- newDataBuffer
resultBuf <- peek resultBufPtr
recArray <- if null recPtrs
then return nullPtr
else do keys <- mapM (peek . unKey) recPtrs
newArray (keys ++ [nullPtr])
ctx <- peek ctxPtr
checkError "op_encrypt" =<< enc_op ctx recArray (fromFlag flag)
plainBuf resultBuf
free plainBufPtr
encResPtr <- c'gpgme_op_encrypt_result ctx
encRes <- peek encResPtr
let recPtr = c'_gpgme_op_encrypt_result'invalid_recipients encRes
let res = if recPtr /= nullPtr
then Left (collectFprs recPtr)
else Right (collectResult resultBuf)
free resultBufPtr
return res
decrypt' :: String -> Encrypted -> IO (Either DecryptError Plain)
decrypt' = decryptInternal' decrypt
decryptVerify' :: String -> Encrypted -> IO (Either DecryptError Plain)
decryptVerify' = decryptInternal' decryptVerify
decryptInternal' :: (Ctx -> Encrypted -> IO (Either DecryptError Plain))
-> String
-> Encrypted
-> IO (Either DecryptError Plain)
decryptInternal' decrFun gpgDir cipher =
withCtx gpgDir locale OpenPGP $ \ctx ->
decrFun ctx cipher
decrypt :: Ctx -> Encrypted -> IO (Either DecryptError Plain)
decrypt = decryptIntern c'gpgme_op_decrypt
decryptVerify :: Ctx -> Encrypted -> IO (Either DecryptError Plain)
decryptVerify = decryptIntern c'gpgme_op_decrypt_verify
decryptIntern :: (C'gpgme_ctx_t
-> C'gpgme_data_t
-> C'gpgme_data_t
-> IO C'gpgme_error_t
)
-> Ctx
-> Encrypted
-> IO (Either DecryptError Plain)
decryptIntern dec_op (Ctx ctxPtr _) cipher = do
cipherBufPtr <- malloc
BS.useAsCString cipher $ \bs -> do
let copyData = 1
let cipherlen = fromIntegral (BS.length cipher)
ret <- c'gpgme_data_new_from_mem cipherBufPtr bs cipherlen copyData
checkError "data_new_from_mem" ret
cipherBuf <- peek cipherBufPtr
resultBufPtr <- newDataBuffer
resultBuf <- peek resultBufPtr
ctx <- peek ctxPtr
errcode <- dec_op ctx cipherBuf resultBuf
let res = if errcode /= noError
then Left (toDecryptError errcode)
else Right (collectResult resultBuf)
free cipherBufPtr
free resultBufPtr
return res
newDataBuffer :: IO (Ptr C'gpgme_data_t)
newDataBuffer = do
resultBufPtr <- malloc
checkError "data_new" =<< c'gpgme_data_new resultBufPtr
return resultBufPtr