module Cachix.Api.Signing
( fingerprint
, passthroughSizeSink
, passthroughHashSink
) where
import Crypto.Hash
import Control.Monad.IO.Class (MonadIO, liftIO)
import qualified Data.ByteArray as BA
import qualified Data.ByteString as BS
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as B16
import Data.Conduit
import qualified Data.Conduit.Combinators as CC
import Data.IORef
import Data.String.Conv (toS)
import qualified Data.Text as T
import Data.Text (Text)
fingerprint :: Text -> Text -> Integer -> [Text] -> ByteString
fingerprint storePath narHash narSize references = toS $ T.intercalate ";"
["1", storePath, narHash, T.pack (show narSize), T.intercalate "," references]
sizeSink :: MonadIO m => ConduitT ByteString o m Integer
sizeSink = CC.foldM (\p n -> return (p + fromIntegral (BS.length n))) 0
hashSink :: MonadIO m => ConduitT ByteString o m (Context SHA256)
hashSink = CC.foldM (\p n -> return (hashUpdate p n)) hashInit
passthroughSizeSink :: MonadIO m => IORef Integer -> ConduitT ByteString ByteString m ()
passthroughSizeSink ioref = passthroughSink sizeSink (liftIO . writeIORef ioref)
passthroughHashSink :: MonadIO m => IORef Text -> ConduitT ByteString ByteString m ()
passthroughHashSink ioref = passthroughSink hashSink (liftIO . writeIORef ioref . transf)
where
transf = toS . B16.encode . BS.pack . BA.unpack . hashFinalize