aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Crypto/Macaroon.hs
diff options
context:
space:
mode:
authorJulien Tanguy <julien.tanguy@jhome.fr>2015-04-09 01:12:36 +0200
committerJulien Tanguy <julien.tanguy@jhome.fr>2015-04-09 01:12:36 +0200
commitf678145637ba6f42c36d07c19f8c764e5d537f72 (patch)
tree3e8578900501968de7404131a89e8e063dd0f12e /src/Crypto/Macaroon.hs
downloadhmacaroons-f678145637ba6f42c36d07c19f8c764e5d537f72.tar.gz
hmacaroons-f678145637ba6f42c36d07c19f8c764e5d537f72.tar.zst
hmacaroons-f678145637ba6f42c36d07c19f8c764e5d537f72.zip
Initial commit
Diffstat (limited to 'src/Crypto/Macaroon.hs')
-rw-r--r--src/Crypto/Macaroon.hs121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/Crypto/Macaroon.hs b/src/Crypto/Macaroon.hs
new file mode 100644
index 0000000..819a9eb
--- /dev/null
+++ b/src/Crypto/Macaroon.hs
@@ -0,0 +1,121 @@
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
11
12Pure haskell implementations of macaroons.
13
14Warning: this implementation has not been audited by security experts.
15Use it with caution.
16
17
18References:
19
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>
22
23-}
24module Crypto.Macaroon (
25 -- * Types
26 Macaroon
27 , Caveat
28 , Key
29 , Location
30 -- * Accessing functions
31 -- ** Macaroons
32 , location
33 , identifier
34 , caveats
35 , signature
36 -- ** Caveats
37 , caveatLoc
38 , caveatId
39 , caveatVId
40
41 -- * Create Macaroons
42 , create
43 , inspect
44 , addFirstPartyCaveat
45 , addThirdPartyCaveat
46
47 -- * Prepare Macaroons for transfer
48 , serialize
49 ) where
50
51import Crypto.Cipher.AES
52import Crypto.Hash
53import Data.Byteable
54import qualified Data.ByteString as BS
55import qualified Data.ByteString.Base64.URL as B64
56import qualified Data.ByteString.Char8 as B8
57import Data.Hex
58
59import Crypto.Macaroon.Internal
60
61-- | Create a Macaroon from its key, identifier and location
62create :: Key -> Key -> Location -> Macaroon
63create secret ident loc = MkMacaroon loc ident [] (toBytes (hmac derivedKey ident :: HMAC SHA256))
64 where
65 derivedKey = toBytes $ (hmac "macaroons-key-generator" secret :: HMAC SHA256)
66
67caveatLoc :: Caveat -> Location
68caveatLoc = cl
69
70caveatId :: Caveat -> Key
71caveatId = cid
72
73caveatVId :: Caveat -> Key
74caveatVId = vid
75
76inspect :: Macaroon -> String
77inspect m = unlines [ "location " ++ show (location m)
78 , "identifier " ++ show (identifier m)
79 , (concatMap (showCav (location m)) (caveats m))
80 , "signature " ++ show (hex $ signature m)
81 ]
82 where
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)
87 ]
88
89serialize :: Macaroon -> BS.ByteString
90serialize m = B8.filter (/= '=') . B64.encode $ packets
91 where
92 packets = BS.concat [ putPacket "location" (location m)
93 , putPacket "identifier" (identifier m)
94 , caveatPackets
95 , putPacket "signature" (signature m)
96 ]
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)
102 ]
103
104
105
106-- | Add a first party Caveat to a Macaroon, with its identifier
107addFirstPartyCaveat :: Key -> Macaroon -> Macaroon
108addFirstPartyCaveat ident m = addCaveat (location m) ident BS.empty m
109
110-- |Add a third party Caveat to a Macaroon, using its location, identifier and
111-- verification key
112addThirdPartyCaveat :: Key
113 -> Key
114 -> Location
115 -> Macaroon
116 -> Macaroon
117addThirdPartyCaveat key cid loc m = addCaveat loc cid vid m
118 where
119 vid = encryptECB (initAES (signature m)) key
120
121