summaryrefslogtreecommitdiffhomepage
path: root/PrevActivity.hs
diff options
context:
space:
mode:
Diffstat (limited to 'PrevActivity.hs')
-rw-r--r--PrevActivity.hs43
1 files changed, 43 insertions, 0 deletions
diff --git a/PrevActivity.hs b/PrevActivity.hs
new file mode 100644
index 0000000..32e647d
--- /dev/null
+++ b/PrevActivity.hs
@@ -0,0 +1,43 @@
+module PrevActivity where
+
+import Types
+import Crypto
+
+import Control.Concurrent.STM
+
+-- | Remove the prevActivity from a message. Doing this before sending
+-- it over the wire saves transmitting that data, without weakening
+-- security at all.
+removePrevActivityHash :: AnyMessage -> AnyMessage
+removePrevActivityHash msg = case msg of
+ User (ActivityMessage a) -> User (go a)
+ Developer (ActivityMessage a) -> Developer (go a)
+ _ -> msg
+ where
+ go a = ActivityMessage $ a { prevActivity = Nothing }
+
+type RecentActivity = STM (SigVerifier, [Hash])
+
+noRecentActivity :: RecentActivity
+noRecentActivity = return (mempty, [])
+
+-- | Restore the prevActivity to a message received without one.
+-- This needs a RecentActivity cache, and it tries hashes from that cache
+-- as the prevActivity until it finds one that makes the message's
+-- signature verify.
+restorePrevActivityHash :: RecentActivity -> AnyMessage -> STM AnyMessage
+restorePrevActivityHash ra msg = case msg of
+ User (ActivityMessage act) ->
+ User . ActivityMessage <$> (go act =<< ra)
+ Developer (ActivityMessage act) ->
+ Developer . ActivityMessage <$> (go act =<< ra)
+ User (ControlMessage {}) -> return msg
+ Developer (ControlMessage {}) -> return msg
+
+ where
+ go act (_, []) = return act
+ go act (sigverifier, (h:hs)) = do
+ let act' = act { prevActivity = Just h }
+ if verifySigned sigverifier act'
+ then return act'
+ else go act (sigverifier, hs)