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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Crypto.Macaroon
Copyright : (c) 2015 Julien Tanguy
License : BSD3
Maintainer : julien.tanguy@jhome.fr
Stability : experimental
Portability : portable
Pure haskell implementations of macaroons.
Warning: this implementation has not been audited by security experts.
Do not use in production
References:
- Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud <http://research.google.com/pubs/pub41892.html>
- Time for better security in NoSQL <http://hackingdistributed.com/2014/11/23/macaroons-in-hyperdex>
-}
module Crypto.Macaroon (
-- * Types
Macaroon
, Caveat
, Key
, Location
, Sig
-- * Accessing functions
-- ** Macaroons
, location
, identifier
, caveats
, signature
-- ** Caveats
, caveatLoc
, caveatId
, caveatVId
-- * Create Macaroons
, create
, inspect
, addFirstPartyCaveat
, addThirdPartyCaveat
) where
import Crypto.Cipher.AES
import Crypto.Hash
import Data.Byteable
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64.URL as B64
import qualified Data.ByteString.Char8 as B8
import Crypto.Macaroon.Internal
-- | Create a Macaroon from its key, identifier and location
create :: Key -> Key -> Location -> Macaroon
create secret ident loc = MkMacaroon loc ident [] (toBytes (hmac derivedKey ident :: HMAC SHA256))
where
derivedKey = toBytes (hmac "macaroons-key-generator" secret :: HMAC SHA256)
-- | Caveat target location
caveatLoc :: Caveat -> Location
caveatLoc = cl
-- | Caveat identifier
caveatId :: Caveat -> Key
caveatId = cid
-- | Caveat verification identifier
caveatVId :: Caveat -> Key
caveatVId = vid
-- | Inspect a macaroon's contents. For debugging purposes.
inspect :: Macaroon -> String
inspect = show
-- | Add a first party Caveat to a Macaroon, with its identifier
addFirstPartyCaveat :: Key -> Macaroon -> Macaroon
addFirstPartyCaveat ident m = addCaveat (location m) ident BS.empty m
-- |Add a third party Caveat to a Macaroon, using its location, identifier and
-- verification key
addThirdPartyCaveat :: Key
-> Key
-> Location
-> Macaroon
-> Macaroon
addThirdPartyCaveat key cid loc m = addCaveat loc cid vid m
where
vid = encryptECB (initAES (signature m)) key
|