diff options
author | Joey Hess <joeyh@joeyh.name> | 2016-09-12 22:35:47 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2016-09-12 22:39:21 -0400 |
commit | 13c408d2295597540f0b2dfb6f7b86e739876c90 (patch) | |
tree | cac72a6d5a75fb15d71d5e86395543829fe2f2df /Storage | |
parent | 483cc9e1fe40899c7f045d71d75aaa5ca99db3fb (diff) | |
download | keysafe-13c408d2295597540f0b2dfb6f7b86e739876c90.tar.gz |
implement client-server Proof Of Work
Mashed up a argon2-based PoW with token buckets and bloom filters.
This is intended to prevent a few abuses including:
* Using a keysafe server for general file storage, by storing a whole
lot of chunks.
* An attacker guessing names that people will use, and uploading junk
to keysafe servers under those names, to make it harder for others to use
keysafe later.
* An attacker trying to guess the names used for objects on keysafe
servers in order to download them and start password cracking.
(As a second level of defense, since the name generation hash
is expensive already.)
Completely untested, but it builds!
This commit was sponsored by Andreas on Patreon.
Diffstat (limited to 'Storage')
-rw-r--r-- | Storage/Network.hs | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/Storage/Network.hs b/Storage/Network.hs index 24f1c7d..6053ff3 100644 --- a/Storage/Network.hs +++ b/Storage/Network.hs @@ -14,8 +14,10 @@ module Storage.Network ( import Types import Types.Storage +import Types.Cost import Data.List import Data.Char +import HTTP import HTTP.Client import HTTP.ProofOfWork import Servant.Client @@ -58,12 +60,12 @@ networkStorage server = Storage store :: Server -> StorableObjectIdent -> Share -> IO StoreResult store srv i (Share _n o) = - serverRequest srv StoreFailure id $ \pow -> + serverRequest srv StoreFailure id i $ \pow -> putObject i pow o retrieve :: Server -> ShareNum -> StorableObjectIdent -> IO RetrieveResult retrieve srv n i = - serverRequest srv RetrieveFailure (RetrieveSuccess . Share n) $ + serverRequest srv RetrieveFailure (RetrieveSuccess . Share n) i $ getObject i -- | Servers should automatically obscure, so do nothing. @@ -72,7 +74,7 @@ obscure :: Server -> IO ObscureResult obscure _ = return ObscureSuccess count :: Server -> IO CountResult -count srv = serverRequest srv CountFailure id countObjects +count srv = either CountFailure id <$> serverRequest' srv countObjects -- | Not needed for servers. move :: Server -> Storage -> IO () @@ -82,23 +84,39 @@ serverRequest :: Server -> (String -> a) -> (r -> a) - -> (Maybe ProofOfWork -> Manager -> BaseUrl -> ExceptT ServantError IO (ProofOfWorkRequirement r)) + -> StorableObjectIdent + -> (Maybe ProofOfWork -> Manager -> BaseUrl -> ExceptT ServantError IO (POWGuarded r)) -> IO a -serverRequest srv onerr onsuccess a = +serverRequest srv onerr onsuccess i a = go Nothing maxProofOfWork + where + go pow (Seconds timeleft) + | timeleft <= 0 = return $ onerr "server asked for too much proof of work; gave up" + | otherwise = do + res <- serverRequest' srv (a pow) + case res of + Left err -> return $ onerr err + Right (Result r) -> return $ onsuccess r + Right (NeedProofOfWork req) -> go + (Just $ genProofOfWork req i) + (Seconds timeleft - generationTime req) + +serverRequest' + :: Server + -> (Manager -> BaseUrl -> ExceptT ServantError IO r) + -> IO (Either String r) +serverRequest' srv a = do -- A new Manager is allocated for each request, rather than reusing -- any connection. This is a feature; it makes correlation attacks -- harder because the server can't tell if two connections - -- (over tor) came from the same user. - go Nothing =<< torableManager + -- accessing different objects came from the same user, except by + -- comparing IP addresses (which are masked somewhat by using tor). + manager <- torableManager + res <- runExceptT $ a manager url + return $ case res of + Left err -> Left $ "server failure: " ++ show err + Right r -> Right r where url = serverUrl srv - go pow manager = do - res <- runExceptT $ a pow manager url - case res of - Left err -> return $ onerr $ - "server failure: " ++ show err - Right (Result r) -> return $ onsuccess r - Right needpow -> error "NEEDPOW" -- loop with pow -- | HTTP Manager supporting tor .onion and regular hosts torableManager :: IO Manager |