module Codec.Crypto.RSA.Exceptions(
         RSAError(..)
       , HashInfo(..)
       -- * Keys and key generation
       , PrivateKey(..)
       , PublicKey(..)
       , generateKeyPair
       -- * High-level encryption and signature functions
       , encrypt
       , encryptOAEP
       , encryptPKCS
       , decrypt
       , decryptOAEP
       , decryptPKCS
       , sign
       , verify
       -- * Core routines for OAEP
       , MGF
       , generateMGF1
       , rsaes_oaep_encrypt
       , rsaes_oaep_decrypt
       -- * Core PSS routines
       -- $pss
       -- * Core PKCS1 (v1.5) Routines
       , rsaes_pkcs1_v1_5_encrypt
       , rsaes_pkcs1_v1_5_decrypt
       , rsassa_pkcs1_v1_5_sign
       , rsassa_pkcs1_v1_5_verify
       -- * Hashing algorithm declarations for use in RSA functions
       , hashSHA1
       , hashSHA224, hashSHA256, hashSHA384, hashSHA512
       -- * Other mathematical functions that are handy for implementing
       -- other RSA primitives.
       , largeRandomPrime
       , generatePQ
       , chunkify
       , os2ip, i2osp
       , rsa_dp, rsa_ep
       , rsa_vp1, rsa_sp1
       , modular_inverse
       , modular_exponentiation
       , randomBS, randomNZBS
       )
 where

import qualified Codec.Crypto.RSA.Pure as Pure
import Codec.Crypto.RSA.Pure(HashInfo,RSAError)
import Crypto.Random
import Crypto.Types.PubKey.RSA
import Data.ByteString.Lazy(ByteString)
import Data.Int

-- |Randomly generate a key pair of the given modules length (in bits) to use
-- in any of the following functions. Use of a good random number generator is
-- of considerable importance when using this function. The input
-- CryptoRandomGen should never be used again for any other purpose; either
-- use the output'd generator or throw it all away.
generateKeyPair :: CryptoRandomGen g =>
                   g -> Int ->
                   (PublicKey, PrivateKey, g)
generateKeyPair :: forall g.
CryptoRandomGen g =>
g -> Int -> (PublicKey, PrivateKey, g)
generateKeyPair g
g Int
sizeBits = Either RSAError (PublicKey, PrivateKey, g)
-> (PublicKey, PrivateKey, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> Int -> Either RSAError (PublicKey, PrivateKey, g)
forall g.
CryptoRandomGen g =>
g -> Int -> Either RSAError (PublicKey, PrivateKey, g)
Pure.generateKeyPair g
g Int
sizeBits)

-- ----------------------------------------------------------------------------

-- |Compute a signature for the given ByteString, using the SHA256 algorithm
-- in the computation. This is currently defined as rsassa_pkcs1_v1_5_sign
-- hashSHA256. If you want to use a different function, simply use the PKCS
-- function, below; it will accept arbitrarily-length messages.
sign :: PrivateKey -> ByteString -> ByteString
sign :: PrivateKey -> ByteString -> ByteString
sign PrivateKey
pk ByteString
bs = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (PrivateKey -> ByteString -> Either RSAError ByteString
Pure.sign PrivateKey
pk ByteString
bs)

-- |Verify a signature for the given ByteString, using the SHA25 algorithm in
-- the computation. Again, if you'd like to use a different algorithm, use the
-- rsassa_pkcs1_v1_5_verify function.
verify :: PublicKey {- ^The key of the signer -} ->
          ByteString {- ^The message -} ->
          ByteString {- ^The purported signature -} ->
          Bool
verify :: PublicKey -> ByteString -> ByteString -> Bool
verify PublicKey
pk ByteString
m ByteString
s = Either RSAError Bool -> Bool
forall e a. Exception e => Either e a -> a
throwLeft (PublicKey -> ByteString -> ByteString -> Either RSAError Bool
Pure.verify PublicKey
pk ByteString
m ByteString
s)

-- ----------------------------------------------------------------------------

-- |Encrypt an arbitrarily-sized message given the public key and reasonable
-- options. This is equivalent to calling encryptOAEP with SHA-256 as the
-- hash function, MGF1(SHA-256) as the mask generation function, and no label.
-- NOTE: This hash choice means that your key size must be 1024 bits or larger.
encrypt :: CryptoRandomGen g =>
           g -> PublicKey -> ByteString ->
           (ByteString, g)
encrypt :: forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> (ByteString, g)
encrypt g
g PublicKey
k ByteString
m = Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
Pure.encrypt g
g PublicKey
k ByteString
m)

-- |Encrypt an arbitrarily-sized message using OAEP encoding. This is the
-- encouraged encoding for doing RSA encryption. Note that your key size
-- must be greater than (2 * hash length + 2) * 8. (For example, the
-- 'encrypt' convenience function uses a 256 bit / 32 byte hash function.
-- Thus, its key must be greater than (2 * 32 + 2) * 8 = 528 bits long,
-- and we suggest 1024 as a lower bound.)
encryptOAEP :: CryptoRandomGen g =>
               g ->
               (ByteString -> ByteString) {- ^The hash function to use -} ->
               MGF {- ^The mask generation function to use -} ->
               ByteString {- ^An optional label to include -} ->
               PublicKey {- ^The public key to encrypt with -} ->
               ByteString {- ^The message to encrypt -} ->
               (ByteString, g)
encryptOAEP :: forall g.
CryptoRandomGen g =>
g
-> (ByteString -> ByteString)
-> MGF
-> ByteString
-> PublicKey
-> ByteString
-> (ByteString, g)
encryptOAEP g
g ByteString -> ByteString
hash MGF
mgf ByteString
l PublicKey
k ByteString
m = Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g
-> (ByteString -> ByteString)
-> MGF
-> ByteString
-> PublicKey
-> ByteString
-> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g
-> (ByteString -> ByteString)
-> MGF
-> ByteString
-> PublicKey
-> ByteString
-> Either RSAError (ByteString, g)
Pure.encryptOAEP g
g ByteString -> ByteString
hash MGF
mgf ByteString
l PublicKey
k ByteString
m)

-- |Encrypt an arbitrarily-sized message using PKCS1 v1.5 encoding. This
-- encoding is deprecated, and should only be used when interacting with
-- legacy software that cannot be modified.
encryptPKCS :: CryptoRandomGen g =>
               g -> PublicKey -> ByteString ->
               (ByteString, g)
encryptPKCS :: forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> (ByteString, g)
encryptPKCS g
g PublicKey
k ByteString
m = Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
Pure.encryptPKCS g
g PublicKey
k ByteString
m)

-- ----------------------------------------------------------------------------

-- |Decrypt an arbitrarily-sized message given the public key and reasonable
-- options. This is equivalent to calling encryptOAEP with SHA-256 as the
-- hash function, MGF1(SHA-256) as the mask generation function, and no label.
decrypt :: PrivateKey -> ByteString -> ByteString
decrypt :: PrivateKey -> ByteString -> ByteString
decrypt PrivateKey
k ByteString
m = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (PrivateKey -> ByteString -> Either RSAError ByteString
Pure.decrypt PrivateKey
k ByteString
m)

-- |Decrypt an arbitrarily-sized message using OAEP encoding. This is the
-- encouraged encoding for doing RSA encryption.
decryptOAEP :: (ByteString -> ByteString) {- ^The hash function to use -} ->
               MGF {- ^The mask generation function to use -} ->
               ByteString {- ^An optional label to include -} ->
               PrivateKey {- ^The public key to encrypt with -} ->
               ByteString {- ^The message to decrypt -} ->
               ByteString
decryptOAEP :: (ByteString -> ByteString)
-> MGF -> ByteString -> PrivateKey -> ByteString -> ByteString
decryptOAEP ByteString -> ByteString
hash MGF
mgf ByteString
l PrivateKey
k ByteString
m = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft ((ByteString -> ByteString)
-> MGF
-> ByteString
-> PrivateKey
-> ByteString
-> Either RSAError ByteString
Pure.decryptOAEP ByteString -> ByteString
hash MGF
mgf ByteString
l PrivateKey
k ByteString
m)

-- |Decrypt an arbitrarily-sized message using PKCS1 v1.5 encoding. This
-- encoding is deprecated, and should only be used when interacting with
-- legacy software that cannot be modified.
decryptPKCS :: PrivateKey -> ByteString -> ByteString
decryptPKCS :: PrivateKey -> ByteString -> ByteString
decryptPKCS PrivateKey
k ByteString
m = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (PrivateKey -> ByteString -> Either RSAError ByteString
Pure.decryptPKCS PrivateKey
k ByteString
m)

-- ----------------------------------------------------------------------------

chunkify :: ByteString -> Int64 -> [ByteString]
chunkify :: ByteString -> Int64 -> [ByteString]
chunkify = ByteString -> Int64 -> [ByteString]
Pure.chunkify

-- ----------------------------------------------------------------------------

-- |The generalized implementation of RSAES-OAEP-ENCRYPT. Using the default
-- instantiontion of this, provided by the 'encrypt' function, is a pretty
-- good plan if this makes no sense to you, as it is instantiated with
-- reasonable defaults.
--
-- The message to be encrypted may not be longer then (k - 2*hLen - 2),
-- where k is the length of the RSA modulus in bytes and hLen is the length
-- of a hash in bytes. Passing in a larger message will generate an error,
-- represented by the Left constructor. Note that this means that OAEP
-- encryption cannot be used with keys smaller than 512 bits.
--
-- I have not put in a check for the length of the label, because I don't
-- expect you to use more than 2^32 bytes. So don't make me regret that, eh?
--
rsaes_oaep_encrypt :: CryptoRandomGen g =>
                      g ->
                      (ByteString->ByteString) {-^The hash function to use-} ->
                      MGF {- ^An appropriate mask genereation function -} ->
                      PublicKey {- ^The recipient's public key -} ->
                      ByteString {- ^A label to associate with the message
                                    (feel free to use BS.empty) -} ->
                      ByteString {- ^The message to encrypt -} ->
                      (ByteString, g)
rsaes_oaep_encrypt :: forall g.
CryptoRandomGen g =>
g
-> (ByteString -> ByteString)
-> MGF
-> PublicKey
-> ByteString
-> ByteString
-> (ByteString, g)
rsaes_oaep_encrypt g
g ByteString -> ByteString
hash MGF
mgf PublicKey
k ByteString
l ByteString
m =
  Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g
-> (ByteString -> ByteString)
-> MGF
-> PublicKey
-> ByteString
-> ByteString
-> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g
-> (ByteString -> ByteString)
-> MGF
-> PublicKey
-> ByteString
-> ByteString
-> Either RSAError (ByteString, g)
Pure.rsaes_oaep_encrypt g
g ByteString -> ByteString
hash MGF
mgf PublicKey
k ByteString
l ByteString
m)

-- |The generalized implementation of RSAES-OAEP-DECRYPT. Again, 'decrypt'
-- initializes this with a pretty good set of defaults if you don't understand
-- what all of the arguments involve.
--
-- The ciphertext message passed to this function must be k bytes long, where
-- k is the size of the modulus in bytes. If it is not, this function will
-- generate an error, represented by the Left constructor.
--
-- Futher, k (the length of the ciphertext in bytes) must be greater than or
-- equal to (2 * hLen + 2), where hLen is the length of the output of the 
-- hash function in bytes. If this equation does not hold, a (different)
-- error will be generated.
--
-- Finally, there are any number of internal situations that may generate
-- an error indicating that decryption failed.
--
rsaes_oaep_decrypt :: (ByteString->ByteString) {-^The hash function to use-} ->
                      MGF {- ^A mask generation function -} ->
                      PrivateKey {- ^The private key to use -} ->
                      ByteString {- ^An optional label whose
                                     association with the message
                                     should be verified. -} ->
                      ByteString {- ^The ciphertext to decrypt -} ->
                      ByteString
rsaes_oaep_decrypt :: (ByteString -> ByteString)
-> MGF -> PrivateKey -> ByteString -> ByteString -> ByteString
rsaes_oaep_decrypt ByteString -> ByteString
hash MGF
mgf PrivateKey
k ByteString
l ByteString
c =
  Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft ((ByteString -> ByteString)
-> MGF
-> PrivateKey
-> ByteString
-> ByteString
-> Either RSAError ByteString
Pure.rsaes_oaep_decrypt ByteString -> ByteString
hash MGF
mgf PrivateKey
k ByteString
l ByteString
c)

-- ----------------------------------------------------------------------------

-- |Implements RSAES-PKCS1-v1.5-Encrypt, for completeness and backward
-- compatibility. Also because I've already written everything else, so why not?
--
-- This encryption / padding mechanism has several known attacks, which are
-- described in the literature. So unless you absolutely need to use this
-- for some historical reason, you should avoid it.
--
-- The message to be encrypted must be less then or equal to (k - 11) bytes
-- long, where k is the length of the key modulus in bytes.
--
-- Because this function uses an unknown amount of randomly-generated data,
-- it takes an instance of RandomGen rather than taking a random number as
-- input, and returns the resultant generator as output. You should take care
-- that you (a) do not reuse the input generator, thus losing important
-- randomness, and (b) choose a decent instance of RandomGen for passing to
-- this function.
rsaes_pkcs1_v1_5_encrypt :: CryptoRandomGen g =>
                            g ->
                            PublicKey ->
                            ByteString ->
                            (ByteString, g)
rsaes_pkcs1_v1_5_encrypt :: forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> (ByteString, g)
rsaes_pkcs1_v1_5_encrypt g
g PublicKey
k ByteString
m =
  Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g -> PublicKey -> ByteString -> Either RSAError (ByteString, g)
Pure.rsaes_pkcs1_v1_5_encrypt g
g PublicKey
k ByteString
m)

-- |Implements RSAES-PKCS1-v1.5-Decrypt, for completeness and possible backward
-- compatibility. Please see the notes for rsaes_pkcs_v1_5_encrypt regarding
-- use of this function in new applications without backwards compatibility
-- requirements.
--
-- The ciphertext message passed to this function must be of length k, where
-- k is the length of the key modulus in bytes.
rsaes_pkcs1_v1_5_decrypt :: PrivateKey -> ByteString -> ByteString
rsaes_pkcs1_v1_5_decrypt :: PrivateKey -> ByteString -> ByteString
rsaes_pkcs1_v1_5_decrypt PrivateKey
k ByteString
c = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (PrivateKey -> ByteString -> Either RSAError ByteString
Pure.rsaes_pkcs1_v1_5_decrypt PrivateKey
k ByteString
c)

-- ----------------------------------------------------------------------------

-- $pss
-- |RSASSA-PSS-Sign, RSASSA-PSS-Verify, and the related functions are not
-- included because they are covered by U.S. Patent 7036014, and it's not clear
-- what the restrictions on implementation are. Sorry.

-- ----------------------------------------------------------------------------

-- |Generate a signature for the given message using the given private key,
-- using the RSASSA-PKCS1-v1.5-Sign algorithm. Note that in researching the
-- requirements for this project, several independent sources suggested not
-- using the same key across sign/validate and encrypt/decrypt contexts. You've
-- been warned.
--
-- The output of this function is the signature only, not the message and
-- the signature.
--
-- SIZE CONSTRAINT: The size of the public key (in bytes) must be greater
-- than or equal to the length of the hash identifier plus the length of
-- a hash plus 1. Thus, for example, you cannot use a 256 bit RSA key with
-- MD5: 32 (the size of a 256-bit RSA key in bytes) is less than 18 (the
-- size of MD5's identier) + 16 (the size of an MD5 hash in bytes) + 1,
-- or 35.
--
-- Thus,
--   * for SHA1 and SHA256, use 512+ bit keys
--   * for SHA384 and SHA512, use 1024+ bit keys
--
rsassa_pkcs1_v1_5_sign :: HashInfo {- ^The hash function to use -} ->
                          PrivateKey {- ^The private key to sign with -} ->
                          ByteString {- ^The message to sign -} ->
                          ByteString -- ^ The signature
rsassa_pkcs1_v1_5_sign :: HashInfo -> PrivateKey -> ByteString -> ByteString
rsassa_pkcs1_v1_5_sign HashInfo
hi PrivateKey
k ByteString
m =
  Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (HashInfo -> PrivateKey -> ByteString -> Either RSAError ByteString
Pure.rsassa_pkcs1_v1_5_sign HashInfo
hi PrivateKey
k ByteString
m)

-- |Validate a signature for the given message using the given public key. The
-- signature must be exactly k bytes long, where k is the size of the RSA
-- modulus IN BYTES.
rsassa_pkcs1_v1_5_verify :: HashInfo {- ^The hash function to use -} ->
                            PublicKey {-^The public key to validate against-} ->
                            ByteString {- ^The message that was signed -} ->
                            ByteString {- ^The purported signature -} ->
                            Bool
rsassa_pkcs1_v1_5_verify :: HashInfo -> PublicKey -> ByteString -> ByteString -> Bool
rsassa_pkcs1_v1_5_verify HashInfo
hi PublicKey
k ByteString
m ByteString
s =
  Either RSAError Bool -> Bool
forall e a. Exception e => Either e a -> a
throwLeft (HashInfo
-> PublicKey -> ByteString -> ByteString -> Either RSAError Bool
Pure.rsassa_pkcs1_v1_5_verify HashInfo
hi PublicKey
k ByteString
m ByteString
s)

-- ----------------------------------------------------------------------------

-- |A 'mask generation function'. The input is a bytestring, and the output
-- is a hash of the given length. Unless you know what you're doing, you 
-- should probably use a MGF1 formulation created with generate_MGF1.
type MGF = ByteString -> Int64 -> Either RSAError ByteString

-- |Generate a mask generation function for the rsaes_oaep_*. As 
-- suggested by the name, the generated function is an instance of the MGF1
-- function. The arguments are the underlying hash function to use and the 
-- size of a hash in bytes.
--
-- The bytestring passed to the generated function cannot be longer than
-- 2^32 * hLen, where hLen is the passed length of the hash. 
generateMGF1 :: (ByteString -> ByteString) -> MGF
generateMGF1 :: (ByteString -> ByteString) -> MGF
generateMGF1 = (ByteString -> ByteString) -> MGF
Pure.generateMGF1

-- ----------------------------------------------------------------------------

-- "i2osp converts a nonnegative integer to an octet string of a specified
-- length" -- RFC 3447
i2osp :: Integral a => a -> Int -> ByteString
i2osp :: forall a. Integral a => a -> Int -> ByteString
i2osp a
x Int
len = Either RSAError ByteString -> ByteString
forall e a. Exception e => Either e a -> a
throwLeft (a -> Int -> Either RSAError ByteString
forall a. Integral a => a -> Int -> Either RSAError ByteString
Pure.i2osp a
x Int
len)

-- "os2ip converts an octet string to a nonnegative integer" - RFC 3447
os2ip :: ByteString -> Integer
os2ip :: ByteString -> Integer
os2ip = ByteString -> Integer
Pure.os2ip

-- the RSA encryption function
rsa_ep :: Integer -> Integer -> Integer -> Integer
rsa_ep :: Integer -> Integer -> Integer -> Integer
rsa_ep Integer
n Integer
e Integer
m = Either RSAError Integer -> Integer
forall e a. Exception e => Either e a -> a
throwLeft (Integer -> Integer -> Integer -> Either RSAError Integer
Pure.rsa_ep Integer
n Integer
e Integer
m)

-- the RSA decryption function
rsa_dp :: Integer -> Integer -> Integer -> Integer
rsa_dp :: Integer -> Integer -> Integer -> Integer
rsa_dp Integer
n Integer
d Integer
c = Either RSAError Integer -> Integer
forall e a. Exception e => Either e a -> a
throwLeft (Integer -> Integer -> Integer -> Either RSAError Integer
Pure.rsa_dp Integer
n Integer
d Integer
c)

-- the RSA signature generation function
rsa_sp1 :: Integer -> Integer -> Integer -> Integer
rsa_sp1 :: Integer -> Integer -> Integer -> Integer
rsa_sp1 Integer
n Integer
d Integer
m = Either RSAError Integer -> Integer
forall e a. Exception e => Either e a -> a
throwLeft (Integer -> Integer -> Integer -> Either RSAError Integer
Pure.rsa_sp1 Integer
n Integer
d Integer
m)

-- the RSA signature verification function
rsa_vp1 :: Integer -> Integer -> Integer -> Integer
rsa_vp1 :: Integer -> Integer -> Integer -> Integer
rsa_vp1 Integer
n Integer
e Integer
s = Either RSAError Integer -> Integer
forall e a. Exception e => Either e a -> a
throwLeft (Integer -> Integer -> Integer -> Either RSAError Integer
Pure.rsa_vp1 Integer
n Integer
e Integer
s)

-- ----------------------------------------------------------------------------

-- Generate p and q. This is not necessarily the best way to do this, but it
-- appears to work. 
generatePQ :: CryptoRandomGen g =>
              g ->
              Int ->
              (Integer, Integer, g)
generatePQ :: forall g. CryptoRandomGen g => g -> Int -> (Integer, Integer, g)
generatePQ g
g Int
len = Either RSAError (Integer, Integer, g) -> (Integer, Integer, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> Int -> Either RSAError (Integer, Integer, g)
forall g.
CryptoRandomGen g =>
g -> Int -> Either RSAError (Integer, Integer, g)
Pure.generatePQ g
g Int
len)

-- |Generate a large random prime of a given length in bytes.
largeRandomPrime :: CryptoRandomGen g => g -> Int -> (Integer, g)
largeRandomPrime :: forall g. CryptoRandomGen g => g -> Int -> (Integer, g)
largeRandomPrime g
g Int
len = Either RSAError (Integer, g) -> (Integer, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> Int -> Either RSAError (Integer, g)
forall g.
CryptoRandomGen g =>
g -> Int -> Either RSAError (Integer, g)
Pure.largeRandomPrime g
g Int
len)

-- |Generate a random ByteString of the given length
randomBS :: CryptoRandomGen g => g -> Int -> (ByteString, g)
randomBS :: forall g. CryptoRandomGen g => g -> Int -> (ByteString, g)
randomBS g
g Int
n = Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> Int -> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g -> Int -> Either RSAError (ByteString, g)
Pure.randomBS g
g Int
n)

-- |Create a random bytestring of non-zero bytes of the given length.
randomNZBS :: CryptoRandomGen g => g -> Int -> (ByteString, g)
randomNZBS :: forall g. CryptoRandomGen g => g -> Int -> (ByteString, g)
randomNZBS g
gen Int
size = Either RSAError (ByteString, g) -> (ByteString, g)
forall e a. Exception e => Either e a -> a
throwLeft (g -> Int -> Either RSAError (ByteString, g)
forall g.
CryptoRandomGen g =>
g -> Int -> Either RSAError (ByteString, g)
Pure.randomNZBS g
gen Int
size)

-- |Computes a^b mod c using a moderately good algorithm.
modular_exponentiation :: Integer -> Integer -> Integer -> Integer
modular_exponentiation :: Integer -> Integer -> Integer -> Integer
modular_exponentiation = Integer -> Integer -> Integer -> Integer
Pure.modular_exponentiation

-- |Compute the modular inverse (d = e^-1 mod phi) via the extended euclidean
-- algorithm.
modular_inverse :: Integer {- ^e -} ->
                   Integer {- ^phi -} ->
                   Integer
modular_inverse :: Integer -> Integer -> Integer
modular_inverse = Integer -> Integer -> Integer
Pure.modular_inverse

-- ----------------------------------------------------------------------------

hashSHA1 :: HashInfo
hashSHA1 :: HashInfo
hashSHA1 = HashInfo
Pure.hashSHA1

hashSHA224 :: HashInfo
hashSHA224 :: HashInfo
hashSHA224 = HashInfo
Pure.hashSHA224

hashSHA256 :: HashInfo
hashSHA256 :: HashInfo
hashSHA256 = HashInfo
Pure.hashSHA256

hashSHA384 :: HashInfo
hashSHA384 :: HashInfo
hashSHA384 = HashInfo
Pure.hashSHA384

hashSHA512 :: HashInfo
hashSHA512 :: HashInfo
hashSHA512 = HashInfo
Pure.hashSHA512