module Crypto.RNCryptor.V3.Encrypt
( encrypt
, encryptBlock
, encryptStream
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Crypto.RNCryptor.Types
import Crypto.RNCryptor.V3.Stream
import Crypto.RNCryptor.Padding
import Crypto.Cipher.AES
import Data.Monoid
import qualified System.IO.Streams as S
encryptBlock :: RNCryptorContext
-> ByteString
-> (RNCryptorContext, ByteString)
encryptBlock ctx clearText =
let cipherText = encryptCBC (ctxCipher ctx) (rncIV . ctxHeader $ ctx) clearText
!sz = B.length clearText
!newHeader = (ctxHeader ctx) { rncIV = (B.drop (sz 16) clearText) }
in (ctx { ctxHeader = newHeader }, cipherText)
encrypt :: RNCryptorContext -> ByteString -> ByteString
encrypt ctx input =
let hdr = ctxHeader ctx
inSz = B.length input
(_, clearText) = encryptBlock ctx (input <> pkcs7Padding blockSize inSz)
in renderRNCryptorHeader hdr <> clearText <> (rncHMAC hdr $ mempty)
encryptStream :: ByteString
-> S.InputStream ByteString
-> S.OutputStream ByteString
-> IO ()
encryptStream userKey inS outS = do
hdr <- newRNCryptorHeader userKey
let ctx = newRNCryptorContext userKey hdr
S.write (Just $ renderRNCryptorHeader hdr) outS
processStream ctx inS outS encryptBlock finaliseEncryption
where
finaliseEncryption lastBlock ctx = do
let inSz = B.length lastBlock
padding = pkcs7Padding blockSize inSz
S.write (Just (snd $ encryptBlock ctx (lastBlock <> padding))) outS
S.write (Just ((rncHMAC . ctxHeader $ ctx) mempty)) outS