]> git.immae.eu Git - github/fretlink/hmacaroons.git/blame - src/Crypto/Macaroon/Verifier.hs
Add Sig/cav verifier
[github/fretlink/hmacaroons.git] / src / Crypto / Macaroon / Verifier.hs
CommitLineData
b92e3c15 1{-# LANGUAGE OverloadedStrings #-}
6f3c0dca 2{-# LANGUAGE RankNTypes #-}
b92e3c15
JT
3{-|
4Module : Crypto.Macaroon.Verifier
5Copyright : (c) 2015 Julien Tanguy
6License : BSD3
7
8Maintainer : julien.tanguy@jhome.fr
9Stability : experimental
10Portability : portable
11
12
13
14-}
6f3c0dca
JT
15module Crypto.Macaroon.Verifier (
16 Verified(..)
62576139 17 , CaveatVerifier
90695615 18 , (<???>)
62576139 19 , verifyMacaroon
6f3c0dca
JT
20 , verifySig
21 , verifyExact
857f2f3b 22 , verifyFun
6f3c0dca 23 , module Data.Attoparsec.ByteString.Char8
62576139 24 , verifyCavs
6f3c0dca 25) where
b92e3c15
JT
26
27
28import Crypto.Hash
29import Data.Bool
30import qualified Data.ByteString as BS
31import Data.Byteable
32import Data.Foldable
90695615 33import Data.Function
6f3c0dca 34import Data.Maybe
90695615 35import Data.Traversable
6f3c0dca
JT
36import Data.Attoparsec.ByteString
37import Data.Attoparsec.ByteString.Char8
b92e3c15
JT
38
39import Crypto.Macaroon.Internal
40
41
42-- | Opaque datatype for now. Might need more explicit errors
6f3c0dca 43data Verified = Ok | Failed deriving (Show,Eq)
b92e3c15 44
6f3c0dca
JT
45instance Monoid Verified where
46 mempty = Ok
47 mappend Ok Ok = Ok
48 mappend _ _ = Failed
49
50
90695615
JT
51data CaveatVerifier = CV { vFun :: Caveat -> Maybe Verified , helpText :: String}
52
53instance Eq CaveatVerifier where
54 (==) = (==) `on` helpText
55
56instance Show CaveatVerifier where
57 show = helpText
58
59(<???>) :: (Caveat -> Maybe Verified) -> String -> CaveatVerifier
60f <???> t = CV f t
6f3c0dca
JT
61
62verifySig :: Key -> Macaroon -> Verified
63verifySig k m = bool Failed Ok $
b92e3c15
JT
64 signature m == foldl' hash (toBytes (hmac derivedKey (identifier m) :: HMAC SHA256)) (caveats m)
65 where
66 hash s c = toBytes (hmac s (vid c `BS.append` cid c) :: HMAC SHA256)
67 derivedKey = toBytes (hmac "macaroons-key-generator" k :: HMAC SHA256)
6f3c0dca 68
62576139
JT
69verifyMacaroon :: Key -> [CaveatVerifier] -> Macaroon -> Verified
70verifyMacaroon secret verifiers m = verifySig secret m `mappend` verifyCavs verifiers m
71
72
90695615
JT
73verifyCavs :: [CaveatVerifier] -> Macaroon -> Verified
74verifyCavs verifiers m = foldMap (\c -> fromMaybe Failed $ foldMap (($ c) . vFun) verifiers) (caveats m)
6f3c0dca 75
857f2f3b
JT
76verifyExact :: (Eq a) => Key -> a -> Parser a -> Caveat -> Maybe Verified
77verifyExact k expected = verifyFun k (expected ==)
78
79verifyFun :: Key -> (a -> Bool) -> Parser a -> Caveat -> Maybe Verified
80verifyFun key f parser cav = if key `BS.isPrefixOf` cid cav then
6f3c0dca 81 case parseOnly kvparser (cid cav) of
857f2f3b 82 Right v -> (bool Failed Ok . f) <$> Just v
6f3c0dca
JT
83 Left _ -> Just Failed
84 else Nothing
85 where
86 kvparser = do
87 key <- string key
88 skipSpace
89 string "="
90 skipSpace
857f2f3b 91 parser <* endOfInput