From 4e96b1f7f18dfa29096132d4b24b856bc958806c Mon Sep 17 00:00:00 2001 From: Dmitry Zuikov Date: Fri, 20 Sep 2024 07:29:36 +0300 Subject: [PATCH] wip --- fixme-new/lib/Fixme/Run/Internal.hs | 121 ++++++++++++------- hbs2-keyman/hbs2-keyman/Main.hs | 5 +- nix/peer/flake.lock | 180 +++++++++++++++++++++++----- nix/peer/flake.nix | 2 +- 4 files changed, 234 insertions(+), 74 deletions(-) diff --git a/fixme-new/lib/Fixme/Run/Internal.hs b/fixme-new/lib/Fixme/Run/Internal.hs index 1b6c6668..3bc5b189 100644 --- a/fixme-new/lib/Fixme/Run/Internal.hs +++ b/fixme-new/lib/Fixme/Run/Internal.hs @@ -39,6 +39,7 @@ import Data.ByteString.Lazy.Char8 qualified as LBS8 import Data.ByteString qualified as BS import Data.Either import Data.Map qualified as Map +import Data.Set qualified as Set import Data.Maybe import Data.HashSet qualified as HS import Data.HashMap.Strict (HashMap) @@ -592,6 +593,9 @@ refchanImport = do here <- selectIsAlreadyScanned x pure $ not here + fixmeGkSign <- putBlock sto "FIXMEGROUPKEYBLOCKv1" <&> fmap HashRef + >>= orThrowUser "hbs2 storage error. aborted" + walkRefChanTx @UNIX goodToGo chan $ \txh u -> do case u of @@ -610,54 +614,42 @@ refchanImport = do P orig (ProposeTran _ box) -> void $ runMaybeT do (_, bs) <- unboxSignedBox0 box & toMPlus - AnnotatedHashRef _ href <- deserialiseOrFail @AnnotatedHashRef (LBS.fromStrict bs) + AnnotatedHashRef sn href <- deserialiseOrFail @AnnotatedHashRef (LBS.fromStrict bs) & toMPlus . either (const Nothing) Just scanned <- lift $ selectIsAlreadyScanned href when (not scanned || ignCached) do - -- check if metadata tx - meta <- runExceptT (extractMetaData @'HBS2Basic (const $ pure Nothing) sto href) - <&> fromRight mempty - - let parsed = parseTop meta & fromRight mempty - - let isGk = not $ L.null [ True | ListVal [SymbolVal "GK:", _] <- parsed ] - - debug $ "metadata:" <+> pretty isGk <+> pretty parsed + let isGk = sn == Just fixmeGkSign if isGk then do - -- TODO: check-error-type - what <- liftIO (runExceptT $ getTreeContents sto href) - <&> either (const Nothing) Just - >>= toMPlus - - gkz <- deserialiseOrFail @[GroupKey 'Symm 'HBS2Basic] what - & toMPlus - - for_ gkz $ \gk -> do - atomically $ writeTQueue tq (Left (txh, orig, href, gk)) + atomically $ writeTQueue tq (Left (txh, orig, href, href)) else do what <- liftIO (runExceptT $ getTreeContents sto href) <&> either (const Nothing) Just >>= toMPlus - exported <- deserialiseOrFail @[FixmeExported] what - & toMPlus + let exported = deserialiseOrFail @[FixmeExported] what + & either (const Nothing) Just - for_ exported $ \e -> do - atomically $ writeTQueue tq (Right (txh, orig, href, e)) + case exported of + Just e -> do + for_ e $ \x -> do + atomically $ writeTQueue tq (Right (txh, orig, href, x)) + + Nothing -> do + lift $ withState $ insertScanned txh imported <- atomically $ flushTQueue tq withState $ transactional do for_ imported $ \case Left (txh, orig, href, gk) -> do - hx <- writeAsMerkle sto (serialise gk) - notice $ "import GK" <+> pretty hx <+> "from" <+> pretty href + -- hx <- writeAsMerkle sto (serialise gk) + -- notice $ "import GK" <+> pretty hx <+> "from" <+> pretty href -- let tx = AnnotatedHashRef _ href <- deserialiseOrFail @AnnotatedHashRef (LBS.fromStrict bs) -- & toMPlus . either (const Nothing) Just insertScanned txh @@ -844,7 +836,6 @@ fixmeRefChanInit = do notice $ green "refchan added" <+> pretty (AsBase58 refchan) - refchanExportGroupKeys :: FixmePerks m => FixmeM m () refchanExportGroupKeys = do @@ -868,6 +859,8 @@ refchanExportGroupKeys = do skip <- newTVarIO HS.empty gkz <- newTVarIO HS.empty + fixmeSign <- putBlock sto "FIXMEGROUPKEYBLOCKv1" <&> fmap HashRef + walkRefChanTx @UNIX goodToGo chan $ \txh u -> do case u of @@ -922,9 +915,16 @@ refchanExportGroupKeys = do let (pk,sk) = (view peerSignPk creds, view peerSignSk creds) - keyz <- Map.fromList <$> S.toList_ do + keyz <- Set.fromList <$> S.toList_ do for_ r $ \gkh -> void $ runMaybeT do + + debug $ red $ "FOR GK" <+> pretty gkh + gk <- loadGroupKeyMaybe @'HBS2Basic sto gkh >>= toMPlus + + -- the original groupkey should be indexed as well + lift $ S.yield gkh + gks <- liftIO (runKeymanClientRO $ findMatchedGroupKeySecret sto gk) when (isNothing gks) do @@ -934,30 +934,69 @@ refchanExportGroupKeys = do gk1 <- generateGroupKey @'HBS2Basic gks (HS.toList $ view refChanHeadReaders rch) let lbs = serialise gk1 - -- gkh1 <- writeAsMerkle sto lbs <&> HashRef + gkh1 <- writeAsMerkle sto lbs <&> HashRef debug $ red "prepare new gk0" <+> pretty (LBS.length lbs) <+> pretty gkh <+> pretty (groupKeyId gk) - lift $ S.yield (groupKeyId gk, gk1) + lift $ S.yield gkh1 - notice $ yellow $ "new gk:" <+> pretty (Map.size keyz) + notice $ yellow $ "new gk:" <+> pretty (Set.size keyz) - let nitems = 262144 `div` (125 * HS.size (view refChanHeadReaders rch) ) - let chunks = Map.elems keyz & chunksOf nitems + -- let nitems = 262144 `div` (125 * HS.size (view refChanHeadReaders rch) ) + -- let chunks = Map.elems keyz & chunksOf nitems - for_ chunks $ \x -> do + -- TODO: gk:performance-vs-reliability + -- ситуация такова: групповой ключ это меркл-дерево + -- для одного и того же блоба могут быть разные меркл-деревья, + -- так как могут быть разные настройки. + -- + -- если распространять ключи по-одному, то хотя бы тот же ключ, + -- который мы создали изначально -- будет доступен по своему хэшу, + -- как отдельный артефакт. + -- + -- Если писать их пачками, где каждый ключ представлен непосредственно, + -- то на принимающей стороне нет гарантии, что меркл дерево будет писаться + -- с таким же параметрами, хотя и может. + -- + -- Решение: делать групповой ключ БЛОКОМ. тогда его размер будет ограничен, + -- но он хотя бы будет всегда однозначно определён хэшем. + -- + -- Решение: ссылаться не на групповой ключ, а на хэш его секрета + -- что ломает текущую схему и обратная совместимость будет морокой. + -- + -- Решение: добавить в hbs2-keyman возможно индексации единичного + -- ключа, и индексировать таким образом *исходные* ключи. + -- + -- Тогда можно эти вот ключи писать пачками, их хэши не имеют особого значения, + -- если мы проиндексируем оригинальный ключ и будем знать, на какой секрет он + -- ссылается. + -- + -- Заметим, что в один блок поместится аж >2000 читателей, что должно быть + -- более, чем достаточно => при таких группах вероятность утечки секрета + -- стремится к 1.0, так как большинство клало болт на меры безопасности. + -- + -- Кстати говоря, проблема недостаточного количества авторов в ключе легко + -- решается полем ORIGIN, т.к мы можем эти самые ключи разделять. + -- + -- Что бы не стоять перед такой проблемой, мы всегда можем распостранять эти ключи + -- по-одному, ЛИБО добавить в производный ключ поле + -- ORIGIN: где будет хэш изначального ключа. + -- + -- Это нормально, так как мы сможем проверить, что у этих ключей + -- (текущий и ORIGIN) одинаковые хэши секретов. + -- + -- Это всё равно оставляет возможность еще одной DoS атаки на сервис, + -- с распространением кривых ключей, но это хотя бы выяснимо, ну и атака + -- может быть только в рамках рефчана, т.е лечится выкидыванием пиров / + -- исключением зловредных авторов. - let gktreemeta = HM.fromList [ ("GK", Text.pack (show $ pretty $ L.length x)) ] - -- group keys are public (and already encrypted) - -- therefore, no encryption - href <- liftIO $ createTreeWithMetadata sto mzero gktreemeta (serialise x) - >>= orThrowPassIO + for_ (Set.toList keyz) $ \href -> do - let tx = AnnotatedHashRef Nothing href + let tx = AnnotatedHashRef fixmeSign href let lbs = serialise tx let box = makeSignedBox @'HBS2Basic @BS.ByteString pk sk (LBS.toStrict lbs) - warn $ "POST GK TX" <+> pretty (length x) <+> "tree" <+> pretty href + warn $ "post gk tx" <+> "tree" <+> pretty href result <- callRpcWaitMay @RpcRefChanPropose (TimeoutSec 1) api (chan, box) diff --git a/hbs2-keyman/hbs2-keyman/Main.hs b/hbs2-keyman/hbs2-keyman/Main.hs index 0047cb7a..bacad32b 100644 --- a/hbs2-keyman/hbs2-keyman/Main.hs +++ b/hbs2-keyman/hbs2-keyman/Main.hs @@ -182,10 +182,7 @@ updateKeys = do let gkz1 = deserialiseOrFail @(GroupKey 'Symm HBS2Basic) gkbs & either mempty List.singleton - let gkz2 = deserialiseOrFail @[GroupKey 'Symm HBS2Basic] gkbs - & fromRight mempty - - for_ (gkz1 <> gkz2) $ \gk -> do + for_ gkz1 $ \gk -> do gkId <- getGroupKeyId gk & toMPlus diff --git a/nix/peer/flake.lock b/nix/peer/flake.lock index 663c7a50..b5e8a73b 100644 --- a/nix/peer/flake.lock +++ b/nix/peer/flake.lock @@ -9,15 +9,16 @@ ] }, "locked": { - "lastModified": 1708680396, - "narHash": "sha256-ZPwDreNdnyCS/hNdaE0OqVhytm+SzZGRfGRTRvBuSzE=", - "ref": "refs/heads/master", - "rev": "221fde04a00a9c38d2f6c0d05b1e1c3457d5a827", - "revCount": 7, + "lastModified": 1713359411, + "narHash": "sha256-BzOZ6xU+Li5nIe71Wy4p+lOEQlYK/e94T0gBcP8IKgE=", + "ref": "generic-sql", + "rev": "03635c54b2e2bd809ec1196bc9082447279f6f24", + "revCount": 9, "type": "git", "url": "https://git.hbs2.net/5xrwbTzzweS9yeJQnrrUY9gQJfhJf84pbyHhF2MMmSft" }, "original": { + "ref": "generic-sql", "type": "git", "url": "https://git.hbs2.net/5xrwbTzzweS9yeJQnrrUY9gQJfhJf84pbyHhF2MMmSft" } @@ -82,6 +83,21 @@ "type": "github" } }, + "flake-utils_10": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "flake-utils_2": { "locked": { "lastModified": 1644229661, @@ -187,6 +203,62 @@ "type": "github" } }, + "flake-utils_9": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "fuzzy": { + "inputs": { + "haskell-flake-utils": "haskell-flake-utils_4", + "nixpkgs": [ + "hbs2", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1715919110, + "narHash": "sha256-moioa3ixAZb0y/xxyxUVjSvXoSiDGXy/vAx6B70d2yM=", + "ref": "refs/heads/master", + "rev": "5a55c22750589b357e50b759d2a754df058446d6", + "revCount": 40, + "type": "git", + "url": "https://git.hbs2.net/GmcLB9gEPT4tbx9eyQiECwsu8oPyEh6qKEpQDtyBWVPA" + }, + "original": { + "type": "git", + "url": "https://git.hbs2.net/GmcLB9gEPT4tbx9eyQiECwsu8oPyEh6qKEpQDtyBWVPA" + } + }, + "fuzzy_2": { + "inputs": { + "haskell-flake-utils": "haskell-flake-utils_8", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1715918584, + "narHash": "sha256-moioa3ixAZb0y/xxyxUVjSvXoSiDGXy/vAx6B70d2yM=", + "rev": "831879978213a1aed15ac70aa116c33bcbe964b8", + "revCount": 63, + "type": "git", + "url": "http://git.hbs2.net/GmcLB9gEPT4tbx9eyQiECwsu8oPyEh6qKEpQDtyBWVPA?tag=0.1.3.1" + }, + "original": { + "rev": "831879978213a1aed15ac70aa116c33bcbe964b8", + "type": "git", + "url": "http://git.hbs2.net/GmcLB9gEPT4tbx9eyQiECwsu8oPyEh6qKEpQDtyBWVPA?tag=0.1.3.1" + } + }, "haskell-flake-utils": { "inputs": { "flake-utils": "flake-utils_2" @@ -245,6 +317,24 @@ "inputs": { "flake-utils": "flake-utils_5" }, + "locked": { + "lastModified": 1707809372, + "narHash": "sha256-wfTL9PlCSOqSSyU4eenFFI7pHrV21gba4GEILnI4nAU=", + "owner": "ivanovs-4", + "repo": "haskell-flake-utils", + "rev": "3cbdc5d6093e8b4464ae64097e0c8c61e4414ff2", + "type": "github" + }, + "original": { + "owner": "ivanovs-4", + "repo": "haskell-flake-utils", + "type": "github" + } + }, + "haskell-flake-utils_5": { + "inputs": { + "flake-utils": "flake-utils_6" + }, "locked": { "lastModified": 1698938553, "narHash": "sha256-oXpTKXioqFbl2mhhvpJIAvgNd+wYyv4ekI+YnJHEJ6s=", @@ -260,9 +350,9 @@ "type": "github" } }, - "haskell-flake-utils_5": { + "haskell-flake-utils_6": { "inputs": { - "flake-utils": "flake-utils_6" + "flake-utils": "flake-utils_7" }, "locked": { "lastModified": 1672412555, @@ -279,9 +369,9 @@ "type": "github" } }, - "haskell-flake-utils_6": { + "haskell-flake-utils_7": { "inputs": { - "flake-utils": "flake-utils_7" + "flake-utils": "flake-utils_8" }, "locked": { "lastModified": 1698938553, @@ -297,9 +387,27 @@ "type": "github" } }, - "haskell-flake-utils_7": { + "haskell-flake-utils_8": { "inputs": { - "flake-utils": "flake-utils_8" + "flake-utils": "flake-utils_9" + }, + "locked": { + "lastModified": 1707809372, + "narHash": "sha256-wfTL9PlCSOqSSyU4eenFFI7pHrV21gba4GEILnI4nAU=", + "owner": "ivanovs-4", + "repo": "haskell-flake-utils", + "rev": "3cbdc5d6093e8b4464ae64097e0c8c61e4414ff2", + "type": "github" + }, + "original": { + "owner": "ivanovs-4", + "repo": "haskell-flake-utils", + "type": "github" + } + }, + "haskell-flake-utils_9": { + "inputs": { + "flake-utils": "flake-utils_10" }, "locked": { "lastModified": 1672412555, @@ -319,7 +427,8 @@ "inputs": { "db-pipe": "db-pipe", "fixme": "fixme", - "haskell-flake-utils": "haskell-flake-utils_4", + "fuzzy": "fuzzy", + "haskell-flake-utils": "haskell-flake-utils_5", "hspup": "hspup", "lsm": "lsm", "nixpkgs": [ @@ -329,17 +438,15 @@ "suckless-conf": "suckless-conf_2" }, "locked": { - "lastModified": 1713159635, - "narHash": "sha256-iXf8qcJxePLM65E0fsAK2kj69/YIyQdNMrZ5yULzVGc=", - "ref": "hbs2-git-index", - "rev": "2289845078ba839bade83a1daf5234435e6e631e", - "revCount": 997, + "lastModified": 1726739166, + "narHash": "sha256-8IXnyZnKZY2kaKNgdYHDzDcMOxxmtSvkQ9HRctSM4xk=", + "rev": "627a3e0911d470b0f06d986d8bc663f934269d0e", + "revCount": 1022, "type": "git", "url": "http://git.hbs2/BTThPdHKF8XnEq4m6wzbKHKA6geLFK4ydYhBXAqBdHSP" }, "original": { - "ref": "hbs2-git-index", - "rev": "2289845078ba839bade83a1daf5234435e6e631e", + "rev": "627a3e0911d470b0f06d986d8bc663f934269d0e", "type": "git", "url": "http://git.hbs2/BTThPdHKF8XnEq4m6wzbKHKA6geLFK4ydYhBXAqBdHSP" } @@ -366,7 +473,7 @@ }, "hspup": { "inputs": { - "haskell-flake-utils": "haskell-flake-utils_5", + "haskell-flake-utils": "haskell-flake-utils_6", "nixpkgs": [ "hbs2", "nixpkgs" @@ -388,7 +495,7 @@ }, "lsm": { "inputs": { - "haskell-flake-utils": "haskell-flake-utils_6", + "haskell-flake-utils": "haskell-flake-utils_7", "nixpkgs": [ "hbs2", "nixpkgs" @@ -425,6 +532,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1707451808, + "narHash": "sha256-UwDBUNHNRsYKFJzyTMVMTF5qS4xeJlWoeyJf+6vvamU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "442d407992384ed9c0e6d352de75b69079904e4e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "442d407992384ed9c0e6d352de75b69079904e4e", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1709200309, "narHash": "sha256-lKdtMbhnBNU1lr978T+wEYet3sfIXXgyiDZNEgx8CV8=", @@ -445,7 +568,7 @@ "extra-container": "extra-container", "hbs2": "hbs2", "home-manager": "home-manager", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" } }, "saltine": { @@ -490,22 +613,23 @@ }, "suckless-conf_2": { "inputs": { - "haskell-flake-utils": "haskell-flake-utils_7", + "fuzzy": "fuzzy_2", + "haskell-flake-utils": "haskell-flake-utils_9", "nixpkgs": [ "hbs2", "nixpkgs" ] }, "locked": { - "lastModified": 1704001322, - "narHash": "sha256-D7T/8wAg5J4KkRw0uB90w3+adY11aQaX7rjmQPXkkQc=", - "ref": "refs/heads/master", - "rev": "8cfc1272bb79ef6ad62ae6a625f21e239916d196", - "revCount": 28, + "lastModified": 1724740155, + "narHash": "sha256-dHAWLoQ0uZ2FckV/93qbXo6aYCTY+jARXiiTgUt6fcA=", + "rev": "b6c5087312e6c09e5c27082da47846f377f73756", + "revCount": 38, "type": "git", "url": "https://git.hbs2.net/JAuk1UJzZfbDGKVazSQU5yYQ3NGfk4gVeZzBCduf5TgQ" }, "original": { + "rev": "b6c5087312e6c09e5c27082da47846f377f73756", "type": "git", "url": "https://git.hbs2.net/JAuk1UJzZfbDGKVazSQU5yYQ3NGfk4gVeZzBCduf5TgQ" } diff --git a/nix/peer/flake.nix b/nix/peer/flake.nix index 32a67549..dd988bce 100644 --- a/nix/peer/flake.nix +++ b/nix/peer/flake.nix @@ -7,7 +7,7 @@ extra-container.url = "github:erikarvstedt/extra-container"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; hbs2.url = - "git+http://git.hbs2/BTThPdHKF8XnEq4m6wzbKHKA6geLFK4ydYhBXAqBdHSP?rev=3b8f3d48f486043c7fa2df5990e5ab96b71996e1"; + "git+http://git.hbs2/BTThPdHKF8XnEq4m6wzbKHKA6geLFK4ydYhBXAqBdHSP?rev=627a3e0911d470b0f06d986d8bc663f934269d0e"; hbs2.inputs.nixpkgs.follows = "nixpkgs"; home-manager.url = "github:nix-community/home-manager";