]> git.immae.eu Git - github/fretlink/hmacaroons.git/blame - src/Crypto/Macaroon.hs
Rewording and lint
[github/fretlink/hmacaroons.git] / src / Crypto / Macaroon.hs
CommitLineData
f6781456
JT
1{-# LANGUAGE OverloadedStrings #-}
2{-|
3Module : Crypto.Macaroon
4Copyright : (c) 2015 Julien Tanguy
5License : BSD3
6
7Maintainer : julien.tanguy@jhome.fr
8Stability : experimental
9Portability : portable
10
f6781456
JT
11Pure haskell implementations of macaroons.
12
13Warning: this implementation has not been audited by security experts.
2aede11a 14Do not use in production
f6781456
JT
15
16
17References:
18
19- Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud <http://research.google.com/pubs/pub41892.html>
20- Time for better security in NoSQL <http://hackingdistributed.com/2014/11/23/macaroons-in-hyperdex>
f6781456
JT
21-}
22module Crypto.Macaroon (
23 -- * Types
24 Macaroon
25 , Caveat
26 , Key
27 , Location
28 -- * Accessing functions
29 -- ** Macaroons
30 , location
31 , identifier
32 , caveats
33 , signature
34 -- ** Caveats
35 , caveatLoc
36 , caveatId
37 , caveatVId
38
39 -- * Create Macaroons
40 , create
41 , inspect
42 , addFirstPartyCaveat
43 , addThirdPartyCaveat
44
45 -- * Prepare Macaroons for transfer
46 , serialize
47 ) where
48
49import Crypto.Cipher.AES
50import Crypto.Hash
2aede11a 51import Data.Char
f6781456
JT
52import Data.Byteable
53import qualified Data.ByteString as BS
54import qualified Data.ByteString.Base64.URL as B64
55import qualified Data.ByteString.Char8 as B8
56import Data.Hex
2aede11a
JT
57import Data.Word
58import Data.Serialize
f6781456
JT
59
60import Crypto.Macaroon.Internal
61
62-- | Create a Macaroon from its key, identifier and location
63create :: Key -> Key -> Location -> Macaroon
64create secret ident loc = MkMacaroon loc ident [] (toBytes (hmac derivedKey ident :: HMAC SHA256))
65 where
2aede11a 66 derivedKey = toBytes (hmac "macaroons-key-generator" secret :: HMAC SHA256)
f6781456
JT
67
68caveatLoc :: Caveat -> Location
69caveatLoc = cl
70
71caveatId :: Caveat -> Key
72caveatId = cid
73
74caveatVId :: Caveat -> Key
75caveatVId = vid
76
77inspect :: Macaroon -> String
2aede11a 78inspect = show
f6781456
JT
79
80serialize :: Macaroon -> BS.ByteString
81serialize m = B8.filter (/= '=') . B64.encode $ packets
82 where
83 packets = BS.concat [ putPacket "location" (location m)
84 , putPacket "identifier" (identifier m)
85 , caveatPackets
86 , putPacket "signature" (signature m)
87 ]
88 caveatPackets = BS.concat $ map (cavPacket (location m)) (caveats m)
89 cavPacket loc c | cl c == loc && vid c == BS.empty = putPacket "cid" (cid c)
90 | otherwise = BS.concat [ putPacket "cid" (cid c)
91 , putPacket "vid" (vid c)
92 , putPacket "cl" (cl c)
93 ]
2aede11a
JT
94 putPacket key dat = BS.concat [
95 B8.map toLower . hex . encode $ (fromIntegral size :: Word16)
96 , key
97 , " "
98 , dat
99 , "\n"
100 ]
101 where
102 size = 4 + 2 + BS.length key + BS.length dat
103
f6781456
JT
104
105
106
107-- | Add a first party Caveat to a Macaroon, with its identifier
108addFirstPartyCaveat :: Key -> Macaroon -> Macaroon
109addFirstPartyCaveat ident m = addCaveat (location m) ident BS.empty m
110
111-- |Add a third party Caveat to a Macaroon, using its location, identifier and
112-- verification key
113addThirdPartyCaveat :: Key
114 -> Key
115 -> Location
116 -> Macaroon
117 -> Macaroon
118addThirdPartyCaveat key cid loc m = addCaveat loc cid vid m
119 where
120 vid = encryptECB (initAES (signature m)) key
121
122