aboutsummaryrefslogtreecommitdiff
path: root/src/Sproxy/Application/State.hs
blob: 8ddbedfcf684eb4824127ae84ce875ede546be7f (plain)
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
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)