wip, decryptBlock + findMatchedGroupKeySecret

This commit is contained in:
Dmitry Zuikov 2024-08-27 08:18:54 +03:00
parent cd694def6d
commit 791d2d1888
4 changed files with 68 additions and 32 deletions

View File

@ -7,16 +7,13 @@ import HBS2.KeyMan.Config
import HBS2.Storage import HBS2.Storage
import HBS2.Data.Types.Refs import HBS2.Data.Types.Refs
import HBS2.Prelude.Plated
import HBS2.Net.Auth.Credentials import HBS2.Net.Auth.Credentials
import HBS2.Net.Auth.GroupKeySymm as Symm import HBS2.Net.Auth.GroupKeySymm as Symm
import HBS2.Net.Proto.Types
import HBS2.System.Dir import HBS2.System.Dir
import Control.Monad.Cont import Control.Monad.Cont
import UnliftIO
import DBPipe.SQLite import DBPipe.SQLite
import Text.InterpolatedString.Perl6 (qc) import Text.InterpolatedString.Perl6 (qc)
import Data.Maybe import Data.Maybe
@ -31,6 +28,8 @@ import Streaming.Prelude qualified as S
data KeyManClientError = KeyManClientSomeError data KeyManClientError = KeyManClientSomeError
newtype KeyManClientEnv = KeyManClientEnv AppEnv
newtype KeyManClient m a = KeyManClient { fromKeyManClient :: DBPipeM m a } newtype KeyManClient m a = KeyManClient { fromKeyManClient :: DBPipeM m a }
deriving newtype ( Applicative deriving newtype ( Applicative
, Functor , Functor
@ -39,29 +38,38 @@ newtype KeyManClient m a = KeyManClient { fromKeyManClient :: DBPipeM m a }
, MonadUnliftIO , MonadUnliftIO
) )
newKeymanClientEnv :: MonadUnliftIO m => m KeyManClientEnv
newKeymanClientEnv = KeyManClientEnv <$> liftIO newAppEnv
withKeymanClientRO :: MonadUnliftIO m => KeyManClientEnv -> KeyManClient m a -> m a
withKeymanClientRO env action = do
let db = appDb (coerce env)
withDB db (fromKeyManClient action)
runKeymanClientRO :: MonadUnliftIO m => KeyManClient m a -> m a runKeymanClientRO :: MonadUnliftIO m => KeyManClient m a -> m a
runKeymanClientRO action = do runKeymanClientRO action = do
dbPath <- getStatePath env <- newKeymanClientEnv
env <- liftIO newAppEnv withKeymanClientRO env action
let db = appDb env
withDB db (fromKeyManClient action)
runKeymanClient :: MonadUnliftIO m => KeyManClient m a -> m a runKeymanClient :: MonadUnliftIO m => KeyManClient m a -> m a
runKeymanClient action = do runKeymanClient action = do
KeyManClientEnv env <- newKeymanClientEnv
-- FIXME: dbpath-to-appstatenv
-- сейчас dbPath берётся из конфига, а db из стейта
-- и хотя они должны быть одинаковы, это не гарантируется
dbPath <- getStatePath dbPath <- getStatePath
env <- liftIO newAppEnv
let db = appDb env let db = appDb env
here <- doesPathExist dbPath
unless here do
withDB db $ populateState
flip runContT pure $ do flip runContT pure $ do
void $ ContT $ bracket (async (runPipe db)) cancel void $ ContT $ bracket (async (runPipe db)) cancel
here <- doesPathExist dbPath
unless here do
withDB db $ populateState
lift $ withDB db (fromKeyManClient action) lift $ withDB db (fromKeyManClient action)
loadCredentials :: forall a m . loadCredentials :: forall a m .
( MonadIO m ( MonadIO m
, SomePubKeyPerks a , SomePubKeyPerks a

View File

@ -35,6 +35,7 @@ syncEntries :: forall c m . ( MonadUnliftIO m
, HasRunDir m , HasRunDir m
, HasTombs m , HasTombs m
, HasCache m , HasCache m
, HasKeyManClient m
, MonadReader (Maybe SyncEnv) m , MonadReader (Maybe SyncEnv) m
) )
=> MakeDictM c m () => MakeDictM c m ()

View File

@ -37,8 +37,11 @@ import HBS2.KeyMan.Keys.Direct as Exported ( runKeymanClient
, loadCredentials , loadCredentials
, loadKeyRingEntries , loadKeyRingEntries
, extractGroupKeySecret , extractGroupKeySecret
, KeyManClientEnv
) )
import HBS2.KeyMan.Keys.Direct qualified as KE
import Data.Config.Suckless as Exported import Data.Config.Suckless as Exported
import Data.Config.Suckless.Script as Exported import Data.Config.Suckless.Script as Exported
@ -112,13 +115,14 @@ instance Pretty DirSyncEnv where
data SyncEnv = data SyncEnv =
SyncEnv SyncEnv
{ refchanAPI :: ServiceCaller RefChanAPI UNIX { refchanAPI :: ServiceCaller RefChanAPI UNIX
, storageAPI :: ServiceCaller StorageAPI UNIX , storageAPI :: ServiceCaller StorageAPI UNIX
, peerAPI :: ServiceCaller PeerAPI UNIX , peerAPI :: ServiceCaller PeerAPI UNIX
, dirSyncEnv :: TVar (Map FilePath DirSyncEnv) , dirSyncEnv :: TVar (Map FilePath DirSyncEnv)
, dirThis :: TVar (Maybe FilePath) , dirThis :: TVar (Maybe FilePath)
, dirTombs :: TVar (Map FilePath (CompactStorage HbSync)) , dirTombs :: TVar (Map FilePath (CompactStorage HbSync))
, dirCache :: TVar (Map FilePath (CompactStorage HbSync)) , dirCache :: TVar (Map FilePath (CompactStorage HbSync))
, keymanClientEnv :: TVar (Maybe KeyManClientEnv)
} }
newtype SyncApp m a = newtype SyncApp m a =
@ -142,6 +146,9 @@ class Monad m => HasCache m where
getCache :: m (CompactStorage HbSync) getCache :: m (CompactStorage HbSync)
closeCache :: m () closeCache :: m ()
class Monad m => HasKeyManClient m where
getKeyManClientEnv :: m KeyManClientEnv
instance MonadUnliftIO m => HasTombs (SyncApp m) where instance MonadUnliftIO m => HasTombs (SyncApp m) where
getTombs = do getTombs = do
SyncEnv{..} <- ask >>= orThrow PeerNotConnectedException SyncEnv{..} <- ask >>= orThrow PeerNotConnectedException
@ -205,6 +212,23 @@ instance MonadUnliftIO m => HasCache (SyncApp m) where
compactStorageClose cache compactStorageClose cache
instance MonadUnliftIO m => HasKeyManClient (SyncApp m) where
getKeyManClientEnv = do
SyncEnv{..} <- ask >>= orThrow PeerNotConnectedException
e <- readTVarIO keymanClientEnv
case e of
Just env -> pure env
-- NOTE: race-but-harmless
-- если у нас в двух потоках позовут этот метод,
-- то будет открыто два соединения, и сохранено
-- последнее. Поскольку соединение readonly это
-- безобидно. В целом, надо навести с этим порядок
Nothing -> do
env <- KE.newKeymanClientEnv
atomically $ writeTVar keymanClientEnv (Just env)
pure env
instance MonadIO m => HasClientAPI StorageAPI UNIX (SyncApp m) where instance MonadIO m => HasClientAPI StorageAPI UNIX (SyncApp m) where
getClientAPI = ask >>= orThrow PeerNotConnectedException getClientAPI = ask >>= orThrow PeerNotConnectedException
<&> storageAPI <&> storageAPI
@ -262,8 +286,9 @@ recover what = do
this <- newTVarIO Nothing this <- newTVarIO Nothing
tombs <- newTVarIO mempty tombs <- newTVarIO mempty
cache <- newTVarIO mempty cache <- newTVarIO mempty
dummyKeyman <- newTVarIO Nothing
let env = Just (SyncEnv refChanAPI storageAPI peerAPI dsync this tombs cache) let env = Just (SyncEnv refChanAPI storageAPI peerAPI dsync this tombs cache dummyKeyman)
liftIO $ withSyncApp env what liftIO $ withSyncApp env what
@ -391,7 +416,8 @@ instance (Monad m, HasCache m) => HasCache (RunM c m) where
getCache = lift getCache getCache = lift getCache
closeCache = lift closeCache closeCache = lift closeCache
instance (MonadUnliftIO m, HasKeyManClient m) => HasKeyManClient (RunM c m) where
getKeyManClientEnv = lift getKeyManClientEnv
-- debugPrefix :: LoggerEntry -> LoggerEntry -- debugPrefix :: LoggerEntry -> LoggerEntry
debugPrefix = toStderr . logPrefix "[debug] " debugPrefix = toStderr . logPrefix "[debug] "

View File

@ -182,6 +182,7 @@ getStateFromDir0 :: ( MonadUnliftIO m
, HasStorage m , HasStorage m
, HasRunDir m , HasRunDir m
, HasCache m , HasCache m
, HasKeyManClient m
) )
=> Bool => Bool
-> m [(FilePath, Entry)] -> m [(FilePath, Entry)]
@ -202,6 +203,7 @@ getStateFromDir :: ( MonadUnliftIO m
, HasStorage m , HasStorage m
, HasRunDir m , HasRunDir m
, HasCache m , HasCache m
, HasKeyManClient m
) )
=> Bool -- ^ use remote state as seed => Bool -- ^ use remote state as seed
-> FilePath -- ^ dir -> FilePath -- ^ dir
@ -245,6 +247,7 @@ getStateFromRefChan :: forall m . ( MonadUnliftIO m
, HasStorage m , HasStorage m
, HasRunDir m , HasRunDir m
, HasCache m , HasCache m
, HasKeyManClient m
) )
=> MyRefChan => MyRefChan
-> m [(FilePath, Entry)] -> m [(FilePath, Entry)]
@ -265,6 +268,8 @@ getStateFromRefChan rchan = do
unless here $ mkdir statePath unless here $ mkdir statePath
keEnv <- getKeyManClientEnv
flip runContT pure do flip runContT pure do
void $ ContT $ bracket (async (runPipe db)) cancel void $ ContT $ bracket (async (runPipe db)) cancel
@ -282,20 +287,15 @@ getStateFromRefChan rchan = do
let members = view refChanHeadReaders rch & HS.toList let members = view refChanHeadReaders rch & HS.toList
krl <- liftIO $ runKeymanClientRO $ loadKeyRingEntries members krl <- liftIO $ withKeymanClientRO keEnv $ loadKeyRingEntries members
<&> L.sortOn (Down . fst) <&> L.sortOn (Down . fst)
<&> fmap snd <&> fmap snd
let krs = HM.fromList [ (pk,e) | e@(KeyringEntry pk _ _) <- krl ] let krs = HM.fromList [ (pk,e) | e@(KeyringEntry pk _ _) <- krl ]
-- FIXME: asap-insert-findMatchedGroupKey -- FIXME: asap-insert-findMatchedGroupKey
let findKey gk = do let findKey gk = lift $ lift $ withKeymanClientRO keEnv do
r <- S.toList_ do findMatchedGroupKeySecret sto gk
forM_ (HM.toList $ recipients gk) $ \(pk,box) -> runMaybeT do
(KeyringEntry ppk ssk _) <- toMPlus $ HM.lookup pk krs
let s = Symm.lookupGroupKey @'HBS2Basic ssk ppk gk
for_ s $ lift . S.yield
pure $ headMay r
-- let check hx = pure True -- let check hx = pure True
hseen <- withDB db (select_ [qc|select txhash from seen|]) hseen <- withDB db (select_ [qc|select txhash from seen|])
@ -641,6 +641,7 @@ runDirectory :: ( IsContext c
, HasRunDir m , HasRunDir m
, HasTombs m , HasTombs m
, HasCache m , HasCache m
, HasKeyManClient m
, Exception (BadFormException c) , Exception (BadFormException c)
) => RunM c m () ) => RunM c m ()
runDirectory = do runDirectory = do