    {-# LANGUAGE DeriveDataTypeable #-}

    -- |
    -- Module      : Crypto.PubKey.Rabin.RW
    -- License     : BSD-style
    -- Maintainer  : Carlos Rodriguez-Vega <crodveg@yahoo.es>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- Rabin-Williams cryptosystem for public-key encryption and digital signature.
    -- See pages 323 - 324 in "Computational Number Theory and Modern Cryptography" by Song Y. Yan.
    -- Also inspired by https://github.com/vanilala/vncrypt/blob/master/vncrypt/vnrw_gmp.c.
    module Crypto.PubKey.Rabin.RW (
        PublicKey (..),
        PrivateKey (..),
        generate,
        encrypt,
        encryptWithSeed,
        decrypt,
        sign,
        verify,
    ) where

    import Data.ByteString
    import Data.Data

    import Crypto.Hash
    import Crypto.Number.Basic (numBytes)
    import Crypto.Number.ModArithmetic (expSafe, jacobi)
    import Crypto.Number.Serialize (i2osp, i2ospOf_, os2ip)
    import Crypto.PubKey.Rabin.OAEP
    import Crypto.PubKey.Rabin.Types
    import Crypto.Random.Types

    -- | Represent a Rabin-Williams public key.
    data PublicKey = PublicKey
        { PublicKey -> Int
    public_size :: Int
        -- ^ size of key in bytes
        , PublicKey -> Integer
    public_n :: Integer
        -- ^ public p*q
        }
        deriving (Int -> PublicKey -> ShowS
    [PublicKey] -> ShowS
    PublicKey -> String
    (Int -> PublicKey -> ShowS)
    -> (PublicKey -> String)
    -> ([PublicKey] -> ShowS)
    -> Show PublicKey
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PublicKey -> ShowS
    showsPrec :: Int -> PublicKey -> ShowS
    $cshow :: PublicKey -> String
    show :: PublicKey -> String
    $cshowList :: [PublicKey] -> ShowS
    showList :: [PublicKey] -> ShowS
    Show, ReadPrec [PublicKey]
    ReadPrec PublicKey
    Int -> ReadS PublicKey
    ReadS [PublicKey]
    (Int -> ReadS PublicKey)
    -> ReadS [PublicKey]
    -> ReadPrec PublicKey
    -> ReadPrec [PublicKey]
    -> Read PublicKey
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS PublicKey
    readsPrec :: Int -> ReadS PublicKey
    $creadList :: ReadS [PublicKey]
    readList :: ReadS [PublicKey]
    $creadPrec :: ReadPrec PublicKey
    readPrec :: ReadPrec PublicKey
    $creadListPrec :: ReadPrec [PublicKey]
    readListPrec :: ReadPrec [PublicKey]
    Read, PublicKey -> PublicKey -> Bool
    (PublicKey -> PublicKey -> Bool)
    -> (PublicKey -> PublicKey -> Bool) -> Eq PublicKey
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PublicKey -> PublicKey -> Bool
    == :: PublicKey -> PublicKey -> Bool
    $c/= :: PublicKey -> PublicKey -> Bool
    /= :: PublicKey -> PublicKey -> Bool
    Eq, Typeable PublicKey
    Typeable PublicKey =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> PublicKey -> c PublicKey)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c PublicKey)
    -> (PublicKey -> Constr)
    -> (PublicKey -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c PublicKey))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey))
    -> ((forall b. Data b => b -> b) -> PublicKey -> PublicKey)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> PublicKey -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> PublicKey -> r)
    -> (forall u. (forall d. Data d => d -> u) -> PublicKey -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> PublicKey -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey)
    -> Data PublicKey
    PublicKey -> Constr
    PublicKey -> DataType
    (forall b. Data b => b -> b) -> PublicKey -> PublicKey
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> PublicKey -> u
    forall u. (forall d. Data d => d -> u) -> PublicKey -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PublicKey
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PublicKey -> c PublicKey
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PublicKey)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PublicKey -> c PublicKey
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PublicKey -> c PublicKey
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PublicKey
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PublicKey
    $ctoConstr :: PublicKey -> Constr
    toConstr :: PublicKey -> Constr
    $cdataTypeOf :: PublicKey -> DataType
    dataTypeOf :: PublicKey -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PublicKey)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PublicKey)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PublicKey)
    $cgmapT :: (forall b. Data b => b -> b) -> PublicKey -> PublicKey
    gmapT :: (forall b. Data b => b -> b) -> PublicKey -> PublicKey
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PublicKey -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> PublicKey -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> PublicKey -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PublicKey -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PublicKey -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PublicKey -> m PublicKey
    Data)

    -- | Represent a Rabin-Williams private key.
    data PrivateKey = PrivateKey
        { PrivateKey -> PublicKey
    private_pub :: PublicKey
        , PrivateKey -> Integer
    private_p :: Integer
        -- ^ p prime number
        , PrivateKey -> Integer
    private_q :: Integer
        -- ^ q prime number
        , PrivateKey -> Integer
    private_d :: Integer
        }
        deriving (Int -> PrivateKey -> ShowS
    [PrivateKey] -> ShowS
    PrivateKey -> String
    (Int -> PrivateKey -> ShowS)
    -> (PrivateKey -> String)
    -> ([PrivateKey] -> ShowS)
    -> Show PrivateKey
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PrivateKey -> ShowS
    showsPrec :: Int -> PrivateKey -> ShowS
    $cshow :: PrivateKey -> String
    show :: PrivateKey -> String
    $cshowList :: [PrivateKey] -> ShowS
    showList :: [PrivateKey] -> ShowS
    Show, ReadPrec [PrivateKey]
    ReadPrec PrivateKey
    Int -> ReadS PrivateKey
    ReadS [PrivateKey]
    (Int -> ReadS PrivateKey)
    -> ReadS [PrivateKey]
    -> ReadPrec PrivateKey
    -> ReadPrec [PrivateKey]
    -> Read PrivateKey
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS PrivateKey
    readsPrec :: Int -> ReadS PrivateKey
    $creadList :: ReadS [PrivateKey]
    readList :: ReadS [PrivateKey]
    $creadPrec :: ReadPrec PrivateKey
    readPrec :: ReadPrec PrivateKey
    $creadListPrec :: ReadPrec [PrivateKey]
    readListPrec :: ReadPrec [PrivateKey]
    Read, PrivateKey -> PrivateKey -> Bool
    (PrivateKey -> PrivateKey -> Bool)
    -> (PrivateKey -> PrivateKey -> Bool) -> Eq PrivateKey
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PrivateKey -> PrivateKey -> Bool
    == :: PrivateKey -> PrivateKey -> Bool
    $c/= :: PrivateKey -> PrivateKey -> Bool
    /= :: PrivateKey -> PrivateKey -> Bool
    Eq, Typeable PrivateKey
    Typeable PrivateKey =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> PrivateKey -> c PrivateKey)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c PrivateKey)
    -> (PrivateKey -> Constr)
    -> (PrivateKey -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c PrivateKey))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c PrivateKey))
    -> ((forall b. Data b => b -> b) -> PrivateKey -> PrivateKey)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r)
    -> (forall u. (forall d. Data d => d -> u) -> PrivateKey -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> PrivateKey -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey)
    -> Data PrivateKey
    PrivateKey -> Constr
    PrivateKey -> DataType
    (forall b. Data b => b -> b) -> PrivateKey -> PrivateKey
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> PrivateKey -> u
    forall u. (forall d. Data d => d -> u) -> PrivateKey -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PrivateKey
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PrivateKey -> c PrivateKey
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PrivateKey)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PrivateKey)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PrivateKey -> c PrivateKey
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PrivateKey -> c PrivateKey
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PrivateKey
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PrivateKey
    $ctoConstr :: PrivateKey -> Constr
    toConstr :: PrivateKey -> Constr
    $cdataTypeOf :: PrivateKey -> DataType
    dataTypeOf :: PrivateKey -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PrivateKey)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PrivateKey)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PrivateKey)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c PrivateKey)
    $cgmapT :: (forall b. Data b => b -> b) -> PrivateKey -> PrivateKey
    gmapT :: (forall b. Data b => b -> b) -> PrivateKey -> PrivateKey
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PrivateKey -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> PrivateKey -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> PrivateKey -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PrivateKey -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PrivateKey -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PrivateKey -> m PrivateKey
    Data)

    -- | Generate a pair of (private, public) key of size in bytes.
    -- Prime p is congruent 3 mod 8 and prime q is congruent 7 mod 8.
    generate
        :: MonadRandom m
        => Int
        -> m (PublicKey, PrivateKey)
    generate :: forall (m :: * -> *).
    MonadRandom m =>
    Int -> m (PublicKey, PrivateKey)
    generate Int
    size = do
        (p, q) <- Int -> PrimeCondition -> PrimeCondition -> m (Integer, Integer)
    forall (m :: * -> *).
    MonadRandom m =>
    Int -> PrimeCondition -> PrimeCondition -> m (Integer, Integer)
    generatePrimes Int
    size (\Integer
    p -> Integer
    p Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` Integer
    8 Integer -> PrimeCondition
    forall a. Eq a => a -> a -> Bool
    == Integer
    3) (\Integer
    q -> Integer
    q Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` Integer
    8 Integer -> PrimeCondition
    forall a. Eq a => a -> a -> Bool
    == Integer
    7)
        return (generateKeys p q)
      where
        generateKeys :: Integer -> Integer -> (PublicKey, PrivateKey)
    generateKeys Integer
    p Integer
    q =
            let n :: Integer
    n = Integer
    p Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    q
                d :: Integer
    d = ((Integer
    p Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * (Integer
    q Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    4 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2
                publicKey :: PublicKey
    publicKey =
                    PublicKey
                        { public_size :: Int
    public_size = Int
    size
                        , public_n :: Integer
    public_n = Integer
    n
                        }
                privateKey :: PrivateKey
    privateKey =
                    PrivateKey
                        { private_pub :: PublicKey
    private_pub = PublicKey
    publicKey
                        , private_p :: Integer
    private_p = Integer
    p
                        , private_q :: Integer
    private_q = Integer
    q
                        , private_d :: Integer
    private_d = Integer
    d
                        }
             in (PublicKey
    publicKey, PrivateKey
    privateKey)

    -- | Encrypt plaintext using public key an a predefined OAEP seed.
    --
    -- See algorithm 8.11 in "Handbook of Applied Cryptography" by Alfred J. Menezes et al.
    encryptWithSeed
        :: HashAlgorithm hash
        => ByteString
        -- ^ Seed
        -> OAEPParams hash ByteString ByteString
        -- ^ OAEP padding
        -> PublicKey
        -- ^ public key
        -> ByteString
        -- ^ plaintext
        -> Either Error ByteString
    encryptWithSeed :: forall hash.
    HashAlgorithm hash =>
    ByteString
    -> OAEPParams hash ByteString ByteString
    -> PublicKey
    -> ByteString
    -> Either Error ByteString
    encryptWithSeed ByteString
    seed OAEPParams hash ByteString ByteString
    oaep PublicKey
    pk ByteString
    m =
        let n :: Integer
    n = PublicKey -> Integer
    public_n PublicKey
    pk
            k :: Int
    k = Integer -> Int
    numBytes Integer
    n
         in do
                m' <- ByteString
    -> OAEPParams hash ByteString ByteString
    -> Int
    -> ByteString
    -> Either Error ByteString
    forall hash.
    HashAlgorithm hash =>
    ByteString
    -> OAEPParams hash ByteString ByteString
    -> Int
    -> ByteString
    -> Either Error ByteString
    pad ByteString
    seed OAEPParams hash ByteString ByteString
    oaep Int
    k ByteString
    m
                m'' <- ep1 n $ os2ip m'
                return $ i2osp $ ep2 n m''

    -- | Encrypt plaintext using public key.
    encrypt
        :: (HashAlgorithm hash, MonadRandom m)
        => OAEPParams hash ByteString ByteString
        -- ^ OAEP padding parameters
        -> PublicKey
        -- ^ public key
        -> ByteString
        -- ^ plaintext
        -> m (Either Error ByteString)
    encrypt :: forall hash (m :: * -> *).
    (HashAlgorithm hash, MonadRandom m) =>
    OAEPParams hash ByteString ByteString
    -> PublicKey -> ByteString -> m (Either Error ByteString)
    encrypt OAEPParams hash ByteString ByteString
    oaep PublicKey
    pk ByteString
    m = do
        seed <- Int -> m ByteString
    forall byteArray. ByteArray byteArray => Int -> m byteArray
    forall (m :: * -> *) byteArray.
    (MonadRandom m, ByteArray byteArray) =>
    Int -> m byteArray
    getRandomBytes Int
    hashLen
        return $ encryptWithSeed seed oaep pk m
      where
        hashLen :: Int
    hashLen = hash -> Int
    forall a. HashAlgorithm a => a -> Int
    hashDigestSize (OAEPParams hash ByteString ByteString -> hash
    forall hash seed output. OAEPParams hash seed output -> hash
    oaepHash OAEPParams hash ByteString ByteString
    oaep)

    -- | Decrypt ciphertext using private key.
    decrypt
        :: HashAlgorithm hash
        => OAEPParams hash ByteString ByteString
        -- ^ OAEP padding parameters
        -> PrivateKey
        -- ^ private key
        -> ByteString
        -- ^ ciphertext
        -> Maybe ByteString
    decrypt :: forall hash.
    HashAlgorithm hash =>
    OAEPParams hash ByteString ByteString
    -> PrivateKey -> ByteString -> Maybe ByteString
    decrypt OAEPParams hash ByteString ByteString
    oaep PrivateKey
    pk ByteString
    c =
        let d :: Integer
    d = PrivateKey -> Integer
    private_d PrivateKey
    pk
            n :: Integer
    n = PublicKey -> Integer
    public_n (PublicKey -> Integer) -> PublicKey -> Integer
    forall a b. (a -> b) -> a -> b
    $ PrivateKey -> PublicKey
    private_pub PrivateKey
    pk
            k :: Int
    k = Integer -> Int
    numBytes Integer
    n
            c' :: ByteString
    c' = Int -> Integer -> ByteString
    forall ba. ByteArray ba => Int -> Integer -> ba
    i2ospOf_ Int
    k (Integer -> ByteString) -> Integer -> ByteString
    forall a b. (a -> b) -> a -> b
    $ Integer -> Integer -> Integer
    dp2 Integer
    n (Integer -> Integer) -> Integer -> Integer
    forall a b. (a -> b) -> a -> b
    $ Integer -> Integer -> Integer -> Integer
    dp1 Integer
    d Integer
    n (Integer -> Integer) -> Integer -> Integer
    forall a b. (a -> b) -> a -> b
    $ ByteString -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip ByteString
    c
         in case OAEPParams hash ByteString ByteString
    -> Int -> ByteString -> Either Error ByteString
    forall hash.
    HashAlgorithm hash =>
    OAEPParams hash ByteString ByteString
    -> Int -> ByteString -> Either Error ByteString
    unpad OAEPParams hash ByteString ByteString
    oaep Int
    k ByteString
    c' of
                Left Error
    _ -> Maybe ByteString
    forall a. Maybe a
    Nothing
                Right ByteString
    p -> ByteString -> Maybe ByteString
    forall a. a -> Maybe a
    Just ByteString
    p

    -- | Sign message using hash algorithm and private key.
    sign
        :: HashAlgorithm hash
        => PrivateKey
        -- ^ private key
        -> hash
        -- ^ hash function
        -> ByteString
        -- ^ message to sign
        -> Either Error Integer
    sign :: forall hash.
    HashAlgorithm hash =>
    PrivateKey -> hash -> ByteString -> Either Error Integer
    sign PrivateKey
    pk hash
    hashAlg ByteString
    m =
        let d :: Integer
    d = PrivateKey -> Integer
    private_d PrivateKey
    pk
            n :: Integer
    n = PublicKey -> Integer
    public_n (PublicKey -> Integer) -> PublicKey -> Integer
    forall a b. (a -> b) -> a -> b
    $ PrivateKey -> PublicKey
    private_pub PrivateKey
    pk
         in do
                m' <- Integer -> Integer -> Either Error Integer
    ep1 Integer
    n (Integer -> Either Error Integer)
    -> Integer -> Either Error Integer
    forall a b. (a -> b) -> a -> b
    $ Digest hash -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip (Digest hash -> Integer) -> Digest hash -> Integer
    forall a b. (a -> b) -> a -> b
    $ hash -> ByteString -> Digest hash
    forall ba alg.
    (ByteArrayAccess ba, HashAlgorithm alg) =>
    alg -> ba -> Digest alg
    hashWith hash
    hashAlg ByteString
    m
                return $ dp1 d n m'

    -- | Verify signature using hash algorithm and public key.
    verify
        :: HashAlgorithm hash
        => PublicKey
        -- ^ public key
        -> hash
        -- ^ hash function
        -> ByteString
        -- ^ message
        -> Integer
        -- ^ signature
        -> Bool
    verify :: forall hash.
    HashAlgorithm hash =>
    PublicKey -> hash -> ByteString -> PrimeCondition
    verify PublicKey
    pk hash
    hashAlg ByteString
    m Integer
    s =
        let n :: Integer
    n = PublicKey -> Integer
    public_n PublicKey
    pk
            h :: Integer
    h = Digest hash -> Integer
    forall ba. ByteArrayAccess ba => ba -> Integer
    os2ip (Digest hash -> Integer) -> Digest hash -> Integer
    forall a b. (a -> b) -> a -> b
    $ hash -> ByteString -> Digest hash
    forall ba alg.
    (ByteArrayAccess ba, HashAlgorithm alg) =>
    alg -> ba -> Digest alg
    hashWith hash
    hashAlg ByteString
    m
            h' :: Integer
    h' = Integer -> Integer -> Integer
    dp2 Integer
    n (Integer -> Integer) -> Integer -> Integer
    forall a b. (a -> b) -> a -> b
    $ Integer -> Integer -> Integer
    ep2 Integer
    n Integer
    s
         in Integer
    h' Integer -> PrimeCondition
    forall a. Eq a => a -> a -> Bool
    == Integer
    h

    -- | Encryption primitive 1
    ep1 :: Integer -> Integer -> Either Error Integer
    ep1 :: Integer -> Integer -> Either Error Integer
    ep1 Integer
    n Integer
    m =
        let m' :: Integer
    m' = Integer
    2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    m Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Integer
    1
            m'' :: Integer
    m'' = Integer
    2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    m'
            m''' :: Integer
    m''' = Integer
    2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    m''
         in case Integer -> Integer -> Maybe Integer
    jacobi Integer
    m' Integer
    n of
                Just (-1) | Integer
    m'' Integer -> PrimeCondition
    forall a. Ord a => a -> a -> Bool
    < Integer
    n -> Integer -> Either Error Integer
    forall a b. b -> Either a b
    Right Integer
    m''
                Just Integer
    1 | Integer
    m''' Integer -> PrimeCondition
    forall a. Ord a => a -> a -> Bool
    < Integer
    n -> Integer -> Either Error Integer
    forall a b. b -> Either a b
    Right Integer
    m'''
                Maybe Integer
    _ -> Error -> Either Error Integer
    forall a b. a -> Either a b
    Left Error
    InvalidParameters

    -- | Encryption primitive 2
    ep2 :: Integer -> Integer -> Integer
    ep2 :: Integer -> Integer -> Integer
    ep2 Integer
    n Integer
    m = Integer -> Integer -> Integer -> Integer
    expSafe Integer
    m Integer
    2 Integer
    n

    -- | Decryption primitive 1
    dp1 :: Integer -> Integer -> Integer -> Integer
    dp1 :: Integer -> Integer -> Integer -> Integer
    dp1 Integer
    d Integer
    n Integer
    c = Integer -> Integer -> Integer -> Integer
    expSafe Integer
    c Integer
    d Integer
    n

    -- | Decryption primitive 2
    dp2 :: Integer -> Integer -> Integer
    dp2 :: Integer -> Integer -> Integer
    dp2 Integer
    n Integer
    c =
        let c' :: Integer
    c' = Integer
    c Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2
            c'' :: Integer
    c'' = (Integer
    n Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    c) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2
         in case Integer
    c Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` Integer
    4 of
                Integer
    0 -> ((Integer
    c' Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2)
                Integer
    1 -> ((Integer
    c'' Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2 Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2)
                Integer
    2 -> ((Integer
    c' Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2)
                Integer
    _ -> ((Integer
    c'' Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `div` Integer
    2)