module Hackage.Security.TUF.FileInfo (
FileInfo(..)
, HashFn(..)
, Hash(..)
, fileInfo
, computeFileInfo
, knownFileInfoEqual
, fileInfoSHA256
, Int54
) where
import Prelude hiding (lookup)
import Data.Map (Map)
import qualified Crypto.Hash.SHA256 as SHA256
import qualified Data.Map as Map
import qualified Data.ByteString.Base16 as Base16
import qualified Data.ByteString.Lazy as BS.L
import qualified Data.ByteString.Char8 as BS.C8
import Hackage.Security.JSON
import Hackage.Security.TUF.Common
import Hackage.Security.Util.Path
data HashFn = HashFnSHA256
deriving (Show, Eq, Ord)
data FileInfo = FileInfo {
fileInfoLength :: FileLength
, fileInfoHashes :: Map HashFn Hash
}
deriving (Show)
fileInfo :: BS.L.ByteString -> FileInfo
fileInfo bs = FileInfo {
fileInfoLength = FileLength . fromIntegral $ BS.L.length bs
, fileInfoHashes = Map.fromList [
(HashFnSHA256, Hash $ BS.C8.unpack $ Base16.encode $ SHA256.hashlazy bs)
]
}
computeFileInfo :: FsRoot root => Path root -> IO FileInfo
computeFileInfo fp = fileInfo <$> readLazyByteString fp
knownFileInfoEqual :: FileInfo -> FileInfo -> Bool
knownFileInfoEqual a b = (==) (fileInfoLength a, fileInfoHashes a)
(fileInfoLength b, fileInfoHashes b)
fileInfoSHA256 :: FileInfo -> Maybe Hash
fileInfoSHA256 FileInfo{..} = Map.lookup HashFnSHA256 fileInfoHashes
instance Monad m => ToObjectKey m HashFn where
toObjectKey HashFnSHA256 = return "sha256"
instance ReportSchemaErrors m => FromObjectKey m HashFn where
fromObjectKey "sha256" = return HashFnSHA256
fromObjectKey str = expected "valid hash function" (Just str)
instance Monad m => ToJSON m FileInfo where
toJSON FileInfo{..} = mkObject [
("length", toJSON fileInfoLength)
, ("hashes", toJSON fileInfoHashes)
]
instance ReportSchemaErrors m => FromJSON m FileInfo where
fromJSON enc = do
fileInfoLength <- fromJSField enc "length"
fileInfoHashes <- fromJSField enc "hashes"
return FileInfo{..}