]> git.immae.eu Git - github/fretlink/hmacaroons.git/commitdiff
Rewording and lint
authorJulien Tanguy <julien.tanguy@jhome.fr>
Thu, 9 Apr 2015 15:29:37 +0000 (17:29 +0200)
committerJulien Tanguy <julien.tanguy@jhome.fr>
Thu, 9 Apr 2015 15:29:37 +0000 (17:29 +0200)
README.md
src/Crypto/Macaroon.hs
src/Crypto/Macaroon/Binder.hs
src/Crypto/Macaroon/Internal.hs
test/Crypto/Macaroon/Tests.hs

index f3fd91a9cb0ba866fad45cbac7dbd07c0d7361c3..45b84e0d4f7aba6c7e15066fec67b940a5b50c0d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -5,14 +5,34 @@ Macaroons is a pure haskell implementation of macaroons. It aims to provide
 compatibility at a serialized level with the [reference implementation](https://github.com/rescrv/libmacaroons)
 and the [python implementation](https://github.com/ecordell/pymacaroons)
 
 compatibility at a serialized level with the [reference implementation](https://github.com/rescrv/libmacaroons)
 and the [python implementation](https://github.com/ecordell/pymacaroons)
 
-[Google paper on macaroons](http://research.google.com/pubs/pub41892.html)
-[Macaroons at Mozilla](https://air.mozilla.org/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/)
-[Time for better security in NoSQL](http://hackingdistributed.com/2014/11/23/macaroons-in-hyperdex/)
-[Pure java implementation](https://github.com/nitram509/jmacaroons)
+**WARNING: This library has not been audited by security experts.**
+**There is no error handling at the moment, everyhting is silently accepted**
+
+It is developed in the purpose of exploration purposes, and would need much
+more attention if it were to be used in production.
+
+References
+==========
+
+Papers and articles
+-------------------
+
+- [Google paper on macaroons](http://research.google.com/pubs/pub41892.html)
+- [Macaroons at Mozilla](https://air.mozilla.org/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/)
+- [Time for better security in NoSQL](http://hackingdistributed.com/2014/11/23/macaroons-in-hyperdex/)
+
+Implementations
+---------------
+
+- [C](https://github.com/rescrv/libmacaroons)
+- [Java](https://github.com/nitram509/jmacaroons)
+- [Python](https://github.com/ecordell/pymacaroons)
 
 TODO
 ====
 
 
 TODO
 ====
 
-- Verifiy Macaroons
+- Verify Macaroons
 - Discharge Macaroons
 - Discharge Macaroons
-
+- JSON serialization
+- Quickcheck tests
+- Error handling
index 819a9ebe4d1d57fca74f984d45b09342c326f600..42e4a0784d946e12e22c881455d4e073f859f348 100644 (file)
@@ -8,18 +8,16 @@ Maintainer  : julien.tanguy@jhome.fr
 Stability   : experimental
 Portability : portable
 
 Stability   : experimental
 Portability : portable
 
-
 Pure haskell implementations of macaroons.
 
 Warning: this implementation has not been audited by security experts.
 Pure haskell implementations of macaroons.
 
 Warning: this implementation has not been audited by security experts.
-Use it with caution.
+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>
 
 
 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
 -}
 module Crypto.Macaroon (
     -- * Types
@@ -50,11 +48,14 @@ module Crypto.Macaroon (
 
 import           Crypto.Cipher.AES
 import           Crypto.Hash
 
 import           Crypto.Cipher.AES
 import           Crypto.Hash
+import           Data.Char
 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           Data.Hex
 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           Data.Hex
+import           Data.Word
+import           Data.Serialize
 
 import           Crypto.Macaroon.Internal
 
 
 import           Crypto.Macaroon.Internal
 
@@ -62,7 +63,7 @@ import           Crypto.Macaroon.Internal
 create :: Key -> Key -> Location -> Macaroon
 create secret ident loc = MkMacaroon loc ident [] (toBytes (hmac derivedKey ident :: HMAC SHA256))
   where
 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)
+    derivedKey = toBytes (hmac "macaroons-key-generator" secret :: HMAC SHA256)
 
 caveatLoc :: Caveat -> Location
 caveatLoc = cl
 
 caveatLoc :: Caveat -> Location
 caveatLoc = cl
@@ -74,17 +75,7 @@ caveatVId :: Caveat -> Key
 caveatVId = vid
 
 inspect :: Macaroon -> String
 caveatVId = vid
 
 inspect :: Macaroon -> String
-inspect m = unlines [ "location " ++ show (location m)
-                    , "identifier " ++ show (identifier m)
-                    , (concatMap (showCav (location m)) (caveats m))
-                    , "signature " ++ show (hex $ signature m)
-                    ]
-  where
-    showCav loc c | cl c == loc && vid c == BS.empty = "cid " ++ show (cid c)
-                  | otherwise = unlines [ "cid " ++ show (cid c)
-                                        , "vid " ++ show (vid c)
-                                        , "cl " ++ show (cl c)
-                                        ]
+inspect = show
 
 serialize :: Macaroon -> BS.ByteString
 serialize m = B8.filter (/= '=') . B64.encode $ packets
 
 serialize :: Macaroon -> BS.ByteString
 serialize m = B8.filter (/= '=') . B64.encode $ packets
@@ -100,6 +91,16 @@ serialize m = B8.filter (/= '=') . B64.encode $ packets
                                             , putPacket "vid" (vid c)
                                             , putPacket "cl" (cl c)
                                             ]
                                             , putPacket "vid" (vid c)
                                             , putPacket "cl" (cl c)
                                             ]
+    putPacket key dat = BS.concat [
+        B8.map toLower . hex . encode $ (fromIntegral size :: Word16)
+        , key
+        , " "
+        , dat
+        , "\n"
+        ]
+      where
+        size = 4 + 2 + BS.length key + BS.length dat
+
 
 
 
 
 
 
index 3ec3d67d8dafee82e87f7117fe10ad9fb1bee43a..91f07ce98c4787baa5d90c1a6ef166b6334d43b1 100644 (file)
@@ -24,5 +24,5 @@ newtype Binder = Binder { bind :: Macaroon -> Macaroon -> BS.ByteString }
 
 -- | Binder which concatenates the two signatures and hashes them
 hashSigs :: Binder
 
 -- | Binder which concatenates the two signatures and hashes them
 hashSigs :: Binder
-hashSigs = Binder $ \m m' -> toBytes (HMAC . hash $ BS.append (toBytes $ signature m') (toBytes $ signature m) :: HMAC SHA256)
+hashSigs = Binder $ \m m' -> toBytes (HMAC . hash $ BS.append (toBytes $ signature m') (toBytes $ signature m) :: HMAC SHA256)
 
 
index fc50486aa42f0a69c95c225b452f0e93a417577e..82ce0b494b28d1d7ebcaa340fa828f53a4d66207 100644 (file)
@@ -21,10 +21,8 @@ import           Data.Byteable
 import qualified Data.ByteString        as BS
 import qualified Data.ByteString.Base64 as B64
 import qualified Data.ByteString.Char8  as B8
 import qualified Data.ByteString        as BS
 import qualified Data.ByteString.Base64 as B64
 import qualified Data.ByteString.Char8  as B8
-import           Data.Char
 import           Data.Hex
 import           Data.Hex
-import           Data.Serialize
-import           Data.Word
+import           Data.List
 
 -- |Type alias for Macaroons and Caveat keys and identifiers
 type Key = BS.ByteString
 
 -- |Type alias for Macaroons and Caveat keys and identifiers
 type Key = BS.ByteString
@@ -45,6 +43,14 @@ data Macaroon = MkMacaroon { location   :: Location
                            -- ^ Macaroon HMAC signature
                            } deriving (Eq)
 
                            -- ^ Macaroon HMAC signature
                            } deriving (Eq)
 
+instance Show Macaroon where
+    -- We use intercalate because unlines would add a trailing newline
+    show (MkMacaroon l i c s) = intercalate "\n" [
+                      "location " ++ B8.unpack l
+                    , "identifier " ++ B8.unpack i
+                    , concatMap show c
+                    , "signature " ++ B8.unpack (hex s)
+                    ]
 
 instance NFData Macaroon where
     rnf (MkMacaroon loc ident cavs sig) = rnf loc `seq` rnf ident `seq` rnf cavs `seq` rnf sig
 
 instance NFData Macaroon where
     rnf (MkMacaroon loc ident cavs sig) = rnf loc `seq` rnf ident `seq` rnf cavs `seq` rnf sig
@@ -60,21 +66,18 @@ data Caveat = MkCaveat { cid :: Key
 
                        } deriving (Eq)
 
 
                        } deriving (Eq)
 
+instance Show Caveat where
+    show (MkCaveat c v l) | v == BS.empty = "cid " ++ B8.unpack c
+                          | otherwise = unlines [ "cid " ++ B8.unpack c
+                                                , "vid " ++ B8.unpack v
+                                                , "cl " ++ B8.unpack l
+                                                ]
+
+
 instance NFData Caveat where
     rnf (MkCaveat cid vid cl) = rnf cid `seq` rnf vid `seq` rnf cl
 
 
 instance NFData Caveat where
     rnf (MkCaveat cid vid cl) = rnf cid `seq` rnf vid `seq` rnf cl
 
 
-putPacket :: BS.ByteString -> BS.ByteString -> BS.ByteString
-putPacket key dat = BS.concat [
-    B8.map toLower . hex . encode $ (fromIntegral size :: Word16)
-    , key
-    , " "
-    , dat
-    , "\n"
-    ]
-  where
-    size = 4 + 2 + BS.length key + BS.length dat
-
 addCaveat :: Location
           -> Key
           -> Key
 addCaveat :: Location
           -> Key
           -> Key
@@ -84,5 +87,5 @@ addCaveat loc cid vid m = m { caveats = cavs ++ [cav'], signature = sig}
   where
     cavs = caveats m
     cav' = MkCaveat cid vid loc
   where
     cavs = caveats m
     cav' = MkCaveat cid vid loc
-    sig = toBytes (hmac (signature m) (BS.append vid cid) :: HMAC SHA256)
+    sig = toBytes (hmac (signature m) (BS.append vid cid) :: HMAC SHA256)
 
 
index cdfb620d13bccc11f6275b531ef8e1767f51ebbe..f57bec363d086883360d08b8691df3da9002611d 100644 (file)
@@ -23,6 +23,7 @@ tests :: TestTree
 tests = testGroup "Crypto.Macaroon" [ basicSignature
                                     , basicSerialize
                                     , basicMint
 tests = testGroup "Crypto.Macaroon" [ basicSignature
                                     , basicSerialize
                                     , basicMint
+                                    , basicInspect
                                     , basicMintTrimmed
                                     ]
 
                                     , basicMintTrimmed
                                     ]
 
@@ -34,12 +35,39 @@ m = create secret key loc
     key = B8.pack "we used our secret key"
     loc = B8.pack "http://mybank/"
 
     key = B8.pack "we used our secret key"
     loc = B8.pack "http://mybank/"
 
+basicSignature = testCase "Basic signature" $
+    "E3D9E02908526C4C0039AE15114115D97FDD68BF2BA379B342AAF0F617D0552F" @=? (hex . signature) m
+
+basicSerialize = testCase "Serialization" $
+    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudG\
+    \lmaWVyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAyZnNpZ25h\
+    \dHVyZSDj2eApCFJsTAA5rhURQRXZf91ovyujebNCqvD2F9BVLwo" @=? serialize m
+
 m2 :: Macaroon
 m2 = addFirstPartyCaveat "test = caveat" m
 
 m2 :: Macaroon
 m2 = addFirstPartyCaveat "test = caveat" m
 
+basicInspect = testCase "Inspect" $
+    "location http://mybank/\nidentifier we used\
+    \ our secret key\ncid test = caveat\nsignature\
+    \ 197BAC7A044AF33332865B9266E26D49\
+    \3BDD668A660E44D88CE1A998C23DBD67" @=? inspect m2
+
+
+basicMint = testCase "First Party Caveat" $
+    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\
+    \WQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegR\
+    \K8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK" @=? serialize m2
+
+
 m3 :: Macaroon
 m3 = addFirstPartyCaveat "test = acaveat" m
 
 m3 :: Macaroon
 m3 = addFirstPartyCaveat "test = acaveat" m
 
+basicMintTrimmed = testCase "Trimmed base64" $
+    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz\
+    \ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln\
+    \bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg" @=? serialize m3
+
+
 m4 :: Macaroon
 m4 = addThirdPartyCaveat caveat_key caveat_id caveat_loc n
   where
 m4 :: Macaroon
 m4 = addThirdPartyCaveat caveat_key caveat_id caveat_loc n
   where
@@ -52,23 +80,5 @@ m4 = addThirdPartyCaveat caveat_key caveat_id caveat_loc n
     caveat_loc = B8.pack "http://auth.mybank/"
 
 
     caveat_loc = B8.pack "http://auth.mybank/"
 
 
-basicSignature = testCase "Basic signature" $
-    "E3D9E02908526C4C0039AE15114115D97FDD68BF2BA379B342AAF0F617D0552F" @=? (hex . signature) m
-
-basicSerialize = testCase "Serialization" $
-    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudG\
-    \lmaWVyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAyZnNpZ25h\
-    \dHVyZSDj2eApCFJsTAA5rhURQRXZf91ovyujebNCqvD2F9BVLwo" @=? serialize m
-
-basicMint = testCase "First Party Caveat" $
-    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\
-    \WQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegR\
-    \K8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK" @=? serialize m2
-
-basicMintTrimmed = testCase "Trimmed base64" $ 
-    "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz\
-    \ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln\
-    \bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg" @=? serialize m3
-
-basicThirdParty = testCase "Third Party Caveat" $ 
+basicThirdParty = testCase "Third Party Caveat" $
     "6B99EDB2EC6D7A4382071D7D41A0BF7DFA27D87D2F9FEA86E330D7850FFDA2B2" @=? (hex . signature) m4
     "6B99EDB2EC6D7A4382071D7D41A0BF7DFA27D87D2F9FEA86E330D7850FFDA2B2" @=? (hex . signature) m4