module Tor.HybridCrypto(
hybridEncrypt
, hybridDecrypt
)
where
import Crypto.Cipher.AES
import Crypto.Cipher.Types
import Crypto.Error
import Crypto.Hash.Algorithms
import Crypto.PubKey.MaskGenFunction
import Crypto.PubKey.RSA.OAEP
import Crypto.PubKey.RSA.Types
import Crypto.Random
import Data.ByteString
import Prelude hiding (length, splitAt)
hybridEncrypt :: MonadRandom m =>
Bool -> PublicKey -> ByteString ->
m ByteString
hybridEncrypt force pubkey m
| not force && (length m < (128 42)) =
failLeft (encrypt oaepParams pubkey m)
| otherwise =
do
kbs <- getRandomBytes 16
let (m1, m2) = splitAt (128 42 16) m
ekm1 <- failLeft (encrypt oaepParams pubkey (kbs `append` m1))
let key = throwCryptoError (cipherInit kbs) :: AES128
em2 = ctrCombine key nullIV m2
return (ekm1 `append` em2)
hybridDecrypt :: MonadRandom m =>
PrivateKey -> ByteString ->
m ByteString
hybridDecrypt privKey em
| length em <= fromIntegral (private_size privKey) =
failLeft (decryptSafer oaepParams privKey em)
| otherwise =
do let (ekm1, em2) = splitAt (fromIntegral (private_size privKey)) em
km1 <- failLeft (decryptSafer oaepParams privKey ekm1)
let (kbs, m1) = splitAt 16 km1
key = throwCryptoError (cipherInit kbs) :: AES128
m2 = ctrCombine key nullIV em2
return (m1 `append` m2)
oaepParams :: OAEPParams SHA1 ByteString ByteString
oaepParams = OAEPParams SHA1 (mgf1 SHA1) Nothing
failLeft :: (Show a, Monad m) => m (Either a b) -> m b
failLeft action =
do v <- action
case v of
Left err ->
fail ("Received unexpected left value (HybridCrypto): " ++ show err)
Right x -> return x