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 -> Int -> [Text] -> ByteString
fingerprint storePath narHash narSize references = toS $ T.intercalate ";"
["1", storePath, narHash, T.pack (show narSize), T.intercalate "," references]
sizeSink :: MonadIO m => Consumer ByteString m Int
sizeSink = CC.foldM (\p n -> return (p + BS.length n)) 0
hashSink :: MonadIO m => Consumer ByteString m (Context SHA256)
hashSink = CC.foldM (\p n -> return (hashUpdate p n)) hashInit
passthroughSizeSink :: MonadIO m => IORef Int -> Conduit ByteString m ByteString
passthroughSizeSink ioref = passthroughSink sizeSink (liftIO . writeIORef ioref)
passthroughHashSink :: MonadIO m => IORef Text -> Conduit ByteString m ByteString
passthroughHashSink ioref = passthroughSink hashSink (liftIO . writeIORef ioref . transf)
where
transf = toS . B16.encode . BS.pack . BA.unpack . hashFinalize