{-# LANGUAGE RankNTypes, CPP #-} module Data.OpenPGP.Util.Decrypt where import qualified Data.ByteString.Lazy as LZ import Crypto.Error import qualified Crypto.Cipher.AES as Vincent import qualified Crypto.Cipher.Blowfish as Vincent import qualified Crypto.Cipher.Types as Vincent import Crypto.Cipher.Cast5 (CAST5_128) import Crypto.Cipher.ThomasToVincent import qualified Data.OpenPGP as OpenPGP import Data.OpenPGP.Util.Base -- decryption codec for withS2K simpleUnCFB :: (Vincent.BlockCipher k) => k -> Vincent.IV k -> LZ.ByteString -> LZ.ByteString simpleUnCFB k iv = padThenUnpad k (toLazyBS . Vincent.cfbDecrypt k iv . LZ.toStrict) withS2K' :: OpenPGP.SymmetricAlgorithm -> Maybe OpenPGP.S2K -> LZ.ByteString -> (forall b. Vincent.BlockCipher b => b -> x) -> x withS2K' OpenPGP.AES128 s2k s f = f (string2key s2k s :: Vincent.AES128) withS2K' OpenPGP.AES192 s2k s f = f (string2key s2k s :: Vincent.AES192) withS2K' OpenPGP.AES256 s2k s f = f (string2key s2k s :: Vincent.AES256) withS2K' OpenPGP.Blowfish s2k s f = f (string2key s2k s :: Vincent.Blowfish128) withS2K' OpenPGP.CAST5 s2k s f = f (string2key s2k s :: ThomasToVincent CAST5_128) string2key :: (Vincent.BlockCipher k) => Maybe OpenPGP.S2K -> LZ.ByteString -> k string2key ms2k s = cipher where #if defined(VERSION_cryptonite) CryptoPassed cipher = Vincent.cipherInit k k = LZ.toStrict $ LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k #else cipher = Vincent.cipherInit k Right k = Vincent.makeKey $ toStrictBS $ LZ.take ksize $ maybe s (\s2k -> OpenPGP.string2key hashBySymbol s2k s) ms2k #endif ksize = case Vincent.cipherKeySize cipher of Vincent.KeySizeFixed n -> fromIntegral n Vincent.KeySizeEnum xs -> error $ "Unknown key size in string2key" Vincent.KeySizeRange min max -> error $ "Unknown key size range in string2key" -- Apply a function f to a zero-padded bytestring s to a multiple -- of the blocksize for cyper k. -- Then drop the same number of bytes from the result of f. padThenUnpad :: (Vincent.BlockCipher k) => k -> (LZ.ByteString -> LZ.ByteString) -> LZ.ByteString -> LZ.ByteString padThenUnpad k f s = dropPadEnd (f padded) where dropPadEnd s = LZ.take (LZ.length s - padAmount) s padded = s `LZ.append` LZ.replicate padAmount 0 padAmount = blksize - (LZ.length s `mod` blksize) blksize = fromIntegral $ Vincent.blockSize k