module Sproxy.Application.State ( decode , encode ) where import Data.ByteString (ByteString) import Data.ByteString.Lazy (fromStrict, toStrict) import Data.Digest.Pure.SHA (hmacSha1, bytestringDigest) import Foreign.C.Types (CTime(..)) import System.Posix.Time (epochTime) import qualified Data.ByteString.Base64 as Base64 import qualified Data.Serialize as DS -- FIXME: Compress / decompress ? encode :: ByteString -> Int -> ByteString -> IO (ByteString, CTime) encode key shelflife payload = do now <- epochTime let expiry = now + (CTime . fromIntegral $ shelflife) d = DS.encode (payload, (\(CTime i64) -> i64) expiry) return (Base64.encode . DS.encode $ (d, digest key d), expiry) decode :: ByteString -> ByteString -> IO (Either String ByteString) decode key raw = do (CTime now) <- epochTime return $ do (d, dgst) <- DS.decode =<< Base64.decode raw if dgst /= digest key d then Left "junk" else do (payload, expiry) <- DS.decode d if expiry < now then Left "expired" else Right payload digest :: ByteString -> ByteString -> ByteString digest key payload = toStrict . bytestringDigest $ hmacSha1 (fromStrict key) (fromStrict payload)