1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
-- CFB.hs: OpenPGP (RFC4880) CFB mode
-- Copyright © 2013-2019 Clint Adams
-- Copyright © 2013 Daniel Kahn Gillmor
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).
module Codec.Encryption.OpenPGP.CFB
( decrypt
, decryptPreservingNonce
, decryptNoNonce
, decryptOpenPGPCfb
, encryptNoNonce
) where
import Codec.Encryption.OpenPGP.BlockCipher (withSymmetricCipher)
import Codec.Encryption.OpenPGP.Internal.HOBlockCipher
import Codec.Encryption.OpenPGP.Types
import qualified Data.ByteString as B
decryptOpenPGPCfb ::
SymmetricAlgorithm
-> B.ByteString
-> B.ByteString
-> Either String B.ByteString
decryptOpenPGPCfb Plaintext ciphertext _ = return ciphertext
decryptOpenPGPCfb sa ciphertext keydata =
withSymmetricCipher sa keydata $ \bc -> do
nonce <- decrypt1 ciphertext bc
cleartext <- decrypt2 ciphertext bc
if nonceCheck bc nonce
then return cleartext
else Left "Session key quickcheck failed"
where
decrypt1 ::
HOBlockCipher cipher
=> B.ByteString
-> cipher
-> Either String B.ByteString
decrypt1 ct cipher =
paddedCfbDecrypt
cipher
(B.replicate (blockSize cipher) 0)
(B.take (blockSize cipher + 2) ct)
decrypt2 ::
HOBlockCipher cipher
=> B.ByteString
-> cipher
-> Either String B.ByteString
decrypt2 ct cipher =
let i = B.take (blockSize cipher) (B.drop 2 ct)
in paddedCfbDecrypt cipher i (B.drop (blockSize cipher + 2) ct)
-- should deprecate this?
decrypt ::
SymmetricAlgorithm
-> B.ByteString
-> B.ByteString
-> Either String B.ByteString
decrypt x y z = snd <$> (decryptPreservingNonce x y z)
decryptPreservingNonce ::
SymmetricAlgorithm
-> B.ByteString
-> B.ByteString
-> Either String (B.ByteString, B.ByteString)
decryptPreservingNonce Plaintext ciphertext _ = return (mempty, ciphertext)
decryptPreservingNonce sa ciphertext keydata =
withSymmetricCipher sa keydata $ \bc -> do
(nonce, cleartext) <-
fmap (B.splitAt (blockSize bc + 2)) (decrypt' ciphertext bc)
if nonceCheck bc nonce
then return (nonce, cleartext)
else Left "Session key quickcheck failed"
where
decrypt' ::
HOBlockCipher cipher
=> B.ByteString
-> cipher
-> Either String B.ByteString
decrypt' ct cipher =
paddedCfbDecrypt cipher (B.replicate (blockSize cipher) 0) ct
decryptNoNonce ::
SymmetricAlgorithm
-> IV
-> B.ByteString
-> B.ByteString
-> Either String B.ByteString
decryptNoNonce Plaintext _ ciphertext _ = return ciphertext
decryptNoNonce sa iv ciphertext keydata =
withSymmetricCipher sa keydata (decrypt' ciphertext)
where
decrypt' ::
HOBlockCipher cipher
=> B.ByteString
-> cipher
-> Either String B.ByteString
decrypt' ct cipher = paddedCfbDecrypt cipher (unIV iv) ct
nonceCheck :: HOBlockCipher cipher => cipher -> B.ByteString -> Bool
nonceCheck bc =
(==) <$> B.take 2 . B.drop (blockSize bc - 2) <*> B.drop (blockSize bc)
encryptNoNonce ::
SymmetricAlgorithm
-> S2K
-> IV
-> B.ByteString
-> B.ByteString
-> Either String B.ByteString
encryptNoNonce Plaintext _ _ payload _ = return payload
encryptNoNonce sa s2k iv payload keydata =
withSymmetricCipher sa keydata (encrypt' payload)
where
encrypt' ::
HOBlockCipher cipher
=> B.ByteString
-> cipher
-> Either String B.ByteString
encrypt' ct cipher = paddedCfbEncrypt cipher (unIV iv) ct
|