{-|
Module      : Botan.Encrypt
Description : Public Key Encryption
Copyright   : (c) Leo D, 2023
License     : BSD-3-Clause
Maintainer  : leo@apotheca.io
Stability   : experimental
Portability : POSIX
-}

module Botan.PubKey.Encrypt
(

-- * Thing
-- $introduction

-- * Usage
-- $usage

-- * Public Key Encryption

  pkEncrypt
, pkEncryptOutputLength

-- ** Data type
, PKEncrypt(..)

-- ** Destructor
, destroyPKEncrypt

-- ** Initializers
, newPKEncrypt

-- ** Accessors
, getPKEncryptOutputLength

-- ** Algorithm
, pkEncryptWith

) where

import qualified Data.ByteString as ByteString

import qualified Botan.Low.PubKey.Encrypt as Low

import Botan.Error
import Botan.Prelude
import Botan.PubKey
import Botan.RNG

{- $introduction

-}

{- $usage

-}

--
-- Public Key Encryption
--

pkEncrypt :: PubKey -> PKPadding -> ByteString -> Maybe ByteString
pkEncrypt :: PubKey -> PKPadding -> ByteString -> Maybe ByteString
pkEncrypt PubKey
pk PKPadding
padding ByteString
plaintext = IO (Maybe ByteString) -> Maybe ByteString
forall a. IO a -> a
unsafePerformIO (IO (Maybe ByteString) -> Maybe ByteString)
-> IO (Maybe ByteString) -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ do
    PKEncrypt
ctx <- PubKey -> PKPadding -> IO PKEncrypt
forall (m :: * -> *).
MonadIO m =>
PubKey -> PKPadding -> m PKEncrypt
newPKEncrypt PubKey
pk PKPadding
padding
    -- TODO: Return nothing on catch error
    ByteString
ciphertext <- PKEncrypt -> ByteString -> IO ByteString
forall (m :: * -> *).
MonadRandomIO m =>
PKEncrypt -> ByteString -> m ByteString
pkEncryptWith PKEncrypt
ctx ByteString
plaintext
    Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ByteString -> IO (Maybe ByteString))
-> Maybe ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
ciphertext
{-# NOINLINE pkEncrypt #-}

pkEncryptOutputLength :: PubKey -> PKPadding -> Int -> Int
pkEncryptOutputLength :: PubKey -> PKPadding -> Int -> Int
pkEncryptOutputLength PubKey
pk PKPadding
padding Int
i = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ do
    PKEncrypt
ctx <- PubKey -> PKPadding -> IO PKEncrypt
forall (m :: * -> *).
MonadIO m =>
PubKey -> PKPadding -> m PKEncrypt
newPKEncrypt PubKey
pk PKPadding
padding
    PKEncrypt -> Int -> IO Int
forall (m :: * -> *). MonadIO m => PKEncrypt -> Int -> m Int
getPKEncryptOutputLength PKEncrypt
ctx Int
i
{-# NOINLINE pkEncryptOutputLength #-}

-- Data type

-- TODO: Maybe rename MutablePKEncrypt or PKEncryptor
type PKEncrypt = Low.Encrypt

-- Destructor

destroyPKEncrypt :: (MonadIO m) => PKEncrypt -> m ()
destroyPKEncrypt :: forall (m :: * -> *). MonadIO m => PKEncrypt -> m ()
destroyPKEncrypt = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (PKEncrypt -> IO ()) -> PKEncrypt -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PKEncrypt -> IO ()
Low.encryptDestroy

-- Initializers

newPKEncrypt :: (MonadIO m) => PubKey -> PKPadding -> m PKEncrypt
newPKEncrypt :: forall (m :: * -> *).
MonadIO m =>
PubKey -> PKPadding -> m PKEncrypt
newPKEncrypt PubKey
pk PKPadding
padding = IO PKEncrypt -> m PKEncrypt
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO PKEncrypt -> m PKEncrypt) -> IO PKEncrypt -> m PKEncrypt
forall a b. (a -> b) -> a -> b
$ PubKey -> ByteString -> IO PKEncrypt
Low.encryptCreate PubKey
pk (PKPadding -> ByteString
pkPaddingName PKPadding
padding)

-- Accessors

-- TODO: Verify
getPKEncryptOutputLength :: (MonadIO m) => PKEncrypt -> Int -> m Int
getPKEncryptOutputLength :: forall (m :: * -> *). MonadIO m => PKEncrypt -> Int -> m Int
getPKEncryptOutputLength PKEncrypt
pkd Int
i = IO Int -> m Int
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m Int) -> IO Int -> m Int
forall a b. (a -> b) -> a -> b
$ PKEncrypt -> Int -> IO Int
Low.encryptOutputLength PKEncrypt
pkd Int
i

-- Algorithm

pkEncryptWith :: (MonadRandomIO m) => PKEncrypt -> ByteString -> m ByteString
pkEncryptWith :: forall (m :: * -> *).
MonadRandomIO m =>
PKEncrypt -> ByteString -> m ByteString
pkEncryptWith PKEncrypt
pkd ByteString
bs = do
    RNG
rng <- m RNG
forall (m :: * -> *). MonadRandomIO m => m RNG
getRNG
    IO ByteString -> m ByteString
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ PKEncrypt -> RNG -> ByteString -> IO ByteString
Low.encrypt PKEncrypt
pkd RNG
rng ByteString
bs