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 (Encrypted -> Encrypted -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Encrypted -> Encrypted -> Bool
$c/= :: Encrypted -> Encrypted -> Bool
== :: Encrypted -> Encrypted -> Bool
$c== :: Encrypted -> Encrypted -> Bool
Eq, Int -> Encrypted -> ShowS
[Encrypted] -> ShowS
Encrypted -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Encrypted] -> ShowS
$cshowList :: [Encrypted] -> ShowS
show :: Encrypted -> String
$cshow :: Encrypted -> String
showsPrec :: Int -> Encrypted -> ShowS
$cshowsPrec :: Int -> Encrypted -> ShowS
Show)

encrypt :: String -> String -> ByteString -> CryptoFailable Encrypted
encrypt :: String -> String -> ByteString -> CryptoFailable Encrypted
encrypt String
stringIV String
key ByteString
secret =
  String -> CryptoFailable AES256
aes256Init String
key forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
  \AES256
context -> case forall b c. (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV forall a b. (a -> b) -> a -> b
$ String -> ByteString
BS.pack String
stringIV of
    Maybe (IV AES256)
Nothing -> forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_IvSizeInvalid
    Just IV AES256
iv -> forall a. a -> CryptoFailable a
CryptoPassed
      forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString -> Encrypted
Encrypted String
stringIV
      forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> ba
ctrCombine AES256
context IV AES256
iv
      forall a b. (a -> b) -> a -> b
$ ByteString
secret

decrypt :: String -> Encrypted -> CryptoFailable ByteString
-- AES/CTR decrypt operation is identical to encrypt
decrypt :: String -> Encrypted -> CryptoFailable ByteString
decrypt String
key (Encrypted String
iv ByteString
secret) = Encrypted -> ByteString
getSecret forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> ByteString -> CryptoFailable Encrypted
encrypt String
iv String
key ByteString
secret

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

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

aes256Init :: String -> CryptoFailable AES256
aes256Init :: String -> CryptoFailable AES256
aes256Init = forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BS.pack