1 {-# LANGUAGE OverloadedStrings #-}
3 Module : Crypto.Macaroon
4 Copyright : (c) 2015 Julien Tanguy
7 Maintainer : julien.tanguy@jhome.fr
8 Stability : experimental
12 Pure haskell implementations of macaroons.
14 Warning: this implementation has not been audited by security experts.
20 - Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud <http://research.google.com/pubs/pub41892.html>
21 - Time for better security in NoSQL <http://hackingdistributed.com/2014/11/23/macaroons-in-hyperdex>
24 module Crypto.Macaroon (
30 -- * Accessing functions
47 -- * Prepare Macaroons for transfer
51 import Crypto.Cipher.AES
54 import qualified Data.ByteString as BS
55 import qualified Data.ByteString.Base64.URL as B64
56 import qualified Data.ByteString.Char8 as B8
59 import Crypto.Macaroon.Internal
61 -- | Create a Macaroon from its key, identifier and location
62 create :: Key -> Key -> Location -> Macaroon
63 create secret ident loc = MkMacaroon loc ident [] (toBytes (hmac derivedKey ident :: HMAC SHA256))
65 derivedKey = toBytes $ (hmac "macaroons-key-generator" secret :: HMAC SHA256)
67 caveatLoc :: Caveat -> Location
70 caveatId :: Caveat -> Key
73 caveatVId :: Caveat -> Key
76 inspect :: Macaroon -> String
77 inspect m = unlines [ "location " ++ show (location m)
78 , "identifier " ++ show (identifier m)
79 , (concatMap (showCav (location m)) (caveats m))
80 , "signature " ++ show (hex $ signature m)
83 showCav loc c | cl c == loc && vid c == BS.empty = "cid " ++ show (cid c)
84 | otherwise = unlines [ "cid " ++ show (cid c)
85 , "vid " ++ show (vid c)
86 , "cl " ++ show (cl c)
89 serialize :: Macaroon -> BS.ByteString
90 serialize m = B8.filter (/= '=') . B64.encode $ packets
92 packets = BS.concat [ putPacket "location" (location m)
93 , putPacket "identifier" (identifier m)
95 , putPacket "signature" (signature m)
97 caveatPackets = BS.concat $ map (cavPacket (location m)) (caveats m)
98 cavPacket loc c | cl c == loc && vid c == BS.empty = putPacket "cid" (cid c)
99 | otherwise = BS.concat [ putPacket "cid" (cid c)
100 , putPacket "vid" (vid c)
101 , putPacket "cl" (cl c)
106 -- | Add a first party Caveat to a Macaroon, with its identifier
107 addFirstPartyCaveat :: Key -> Macaroon -> Macaroon
108 addFirstPartyCaveat ident m = addCaveat (location m) ident BS.empty m
110 -- |Add a third party Caveat to a Macaroon, using its location, identifier and
112 addThirdPartyCaveat :: Key
117 addThirdPartyCaveat key cid loc m = addCaveat loc cid vid m
119 vid = encryptECB (initAES (signature m)) key