module Crypto.Encryption (Encrypted(..)
                        , getIV
                        , getSecret
                        , encrypt
                        , decrypt) where

import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS
import Crypto.Error (CryptoFailable(..), CryptoError(..))
import Crypto.Cipher.AES (AES256)
import Crypto.Cipher.Types (BlockCipher(..), Cipher(..), makeIV)

data Encrypted = Encrypted String ByteString deriving (Eq, Show)

encrypt :: String -> String -> ByteString -> CryptoFailable Encrypted
encrypt stringIV key secret =
  aes256Init key >>=
  \context -> case makeIV $ BS.pack stringIV of
    Nothing -> CryptoFailed CryptoError_IvSizeInvalid
    Just iv -> CryptoPassed
      . Encrypted stringIV
      . ctrCombine context iv
      $ secret

decrypt :: String -> Encrypted -> CryptoFailable ByteString
-- AES/CTR decrypt operation is identical to encrypt
decrypt key (Encrypted iv secret) = getSecret <$> encrypt iv key secret

getIV :: Encrypted -> String
getIV (Encrypted iv _) = iv

getSecret :: Encrypted -> ByteString
getSecret (Encrypted _ secret) = secret

aes256Init :: String -> CryptoFailable AES256
aes256Init = cipherInit . BS.pack