hackage-security-0.6.2.6: Hackage security library

Safe Haskell | None
Language | Haskell2010

Hackage.Security.Client

Contents

- Checking for updates
- Downloading targets
- Access to the Hackage index
- Bootstrapping
- Re-exports
  - We only a few bits from .Repository
- Exceptions

Description

Main entry point into the Hackage Security framework for clients

Synopsis

- checkForUpdates :: forall (down :: Type -> Type). (Throws VerificationError, Throws SomeRemoteError) => Repository down -> Maybe UTCTime -> IO HasUpdates
- data HasUpdates
  - = HasUpdates
  - | NoUpdates
- downloadPackage :: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError, Throws InvalidPackageException) => Repository down -> PackageIdentifier -> Path Absolute -> IO ()
- downloadPackage' :: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError, Throws InvalidPackageException) => Repository down -> PackageIdentifier -> FilePath -> IO ()
- data Directory = Directory {
  - directoryFirst :: DirectoryEntry
  - directoryNext :: DirectoryEntry
  - directoryLookup :: forall dec. IndexFile dec -> Maybe DirectoryEntry
  - directoryEntries :: [(DirectoryEntry, IndexPath, Maybe (Some IndexFile))]
  }
- newtype DirectoryEntry = DirectoryEntry {
  - directoryEntryBlockNo :: TarEntryOffset
  }
- getDirectory :: forall (down :: Type -> Type). Repository down -> IO Directory
- data IndexFile a where
  - IndexPkgMetadata :: PackageIdentifier -> IndexFile (Signed Targets)
  - IndexPkgCabal :: PackageIdentifier -> IndexFile ()
  - IndexPkgPrefs :: PackageName -> IndexFile ()
- data IndexEntry dec = IndexEntry {
  - indexEntryPath :: IndexPath
  - indexEntryPathParsed :: Maybe (IndexFile dec)
  - indexEntryContent :: ByteString
  - indexEntryContentParsed :: Either SomeException dec
  - indexEntryTime :: EpochTime
  }
- data IndexCallbacks = IndexCallbacks {
  - indexLookupEntry :: DirectoryEntry -> IO (Some IndexEntry, Maybe DirectoryEntry)
  - indexLookupFile :: forall dec. IndexFile dec -> IO (Maybe (IndexEntry dec))
  - indexLookupFileEntry :: forall dec. DirectoryEntry -> IndexFile dec -> IO (IndexEntry dec)
  - indexLookupCabal :: Throws InvalidPackageException => PackageIdentifier -> IO (Trusted ByteString)
  - indexLookupMetadata :: Throws InvalidPackageException => PackageIdentifier -> IO (Trusted Targets)
  - indexLookupFileInfo :: (Throws InvalidPackageException, Throws VerificationError) => PackageIdentifier -> IO (Trusted FileInfo)
  - indexLookupHash :: (Throws InvalidPackageException, Throws VerificationError) => PackageIdentifier -> IO (Trusted Hash)
  - indexDirectory :: Directory
  }
- withIndex :: forall (down :: Type -> Type) a. Repository down -> (IndexCallbacks -> IO a) -> IO a
- requiresBootstrap :: forall (down :: Type -> Type). Repository down -> IO Bool
- bootstrap :: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError) => Repository down -> [KeyId] -> KeyThreshold -> IO ()
- data Signed a = Signed {
  - signed :: a
  - signatures :: Signatures
  }
- data Signature = Signature {
  - signature :: ByteString
  - signatureKey :: Some PublicKey
  }
- data IndexFile a where
  - IndexPkgMetadata :: PackageIdentifier -> IndexFile (Signed Targets)
  - IndexPkgCabal :: PackageIdentifier -> IndexFile ()
  - IndexPkgPrefs :: PackageName -> IndexFile ()
- data FileMap
- data TargetPath
  - = TargetPathRepo RepoPath
  - | TargetPathIndex IndexPath
- data FileChange
  - = FileChanged FileInfo
  - | FileDeleted
- fileMapChanges :: FileMap -> FileMap -> Map TargetPath FileChange
- data FileInfo = FileInfo {
  - fileInfoLength :: FileLength
  - fileInfoHashes :: Map HashFn Hash
  }
- data Int54
- data Header = Header {
  - headerExpires :: FileExpires
  - headerVersion :: FileVersion
  }
- data Mirrors = Mirrors {
  - mirrorsVersion :: FileVersion
  - mirrorsExpires :: FileExpires
  - mirrorsMirrors :: [Mirror]
  }
- data Root = Root {
  - rootVersion :: FileVersion
  - rootExpires :: FileExpires
  - rootKeys :: KeyEnv
  - rootRoles :: RootRoles
  }
- data Snapshot = Snapshot {
  - snapshotVersion :: FileVersion
  - snapshotExpires :: FileExpires
  - snapshotInfoRoot :: FileInfo
  - snapshotInfoMirrors :: FileInfo
  - snapshotInfoTarGz :: FileInfo
  - snapshotInfoTar :: Maybe FileInfo
  }
- data Targets = Targets {
  - targetsVersion :: FileVersion
  - targetsExpires :: FileExpires
  - targetsTargets :: FileMap
  - targetsDelegations :: Maybe Delegations
  }
- data Timestamp = Timestamp {
  - timestampVersion :: FileVersion
  - timestampExpires :: FileExpires
  - timestampInfoSnapshot :: FileInfo
  }
- newtype FileLength = FileLength {
  - fileLength :: Int54
  }
- newtype Hash = Hash String
- newtype KeyThreshold = KeyThreshold Int54
- data HashFn
  - = HashFnSHA256
  - | HashFnMD5
- fileInfo :: ByteString -> FileInfo
- computeFileInfo :: FsRoot root => Path root -> IO FileInfo
- compareTrustedFileInfo :: FileInfo -> FileInfo -> Bool
- knownFileInfoEqual :: FileInfo -> FileInfo -> Bool
- fileInfoSHA256 :: FileInfo -> Maybe Hash
- class HasHeader a where
  - fileExpires :: Lens' a FileExpires
  - fileVersion :: Lens' a FileVersion
- newtype FileVersion = FileVersion Int54
- newtype FileExpires = FileExpires (Maybe UTCTime)
- expiresInDays :: UTCTime -> Integer -> FileExpires
- expiresNever :: FileExpires
- isExpired :: UTCTime -> FileExpires -> Bool
- versionInitial :: FileVersion
- versionIncrement :: FileVersion -> FileVersion
- data CacheLayout = CacheLayout {
  - cacheLayoutRoot :: CachePath
  - cacheLayoutTimestamp :: CachePath
  - cacheLayoutSnapshot :: CachePath
  - cacheLayoutMirrors :: CachePath
  - cacheLayoutIndexTar :: CachePath
  - cacheLayoutIndexIdx :: CachePath
  - cacheLayoutIndexTarGz :: CachePath
  }
- cabalCacheLayout :: CacheLayout
- data IndexLayout = IndexLayout {
  - indexFileToPath :: forall dec. IndexFile dec -> IndexPath
  - indexFileFromPath :: IndexPath -> Maybe (Some IndexFile)
  }
- hackageIndexLayout :: IndexLayout
- indexLayoutPkgMetadata :: IndexLayout -> PackageIdentifier -> IndexPath
- indexLayoutPkgCabal :: IndexLayout -> PackageIdentifier -> IndexPath
- indexLayoutPkgPrefs :: IndexLayout -> PackageName -> IndexPath
- data RepoLayout = RepoLayout {
  - repoLayoutRoot :: RepoPath
  - repoLayoutTimestamp :: RepoPath
  - repoLayoutSnapshot :: RepoPath
  - repoLayoutMirrors :: RepoPath
  - repoLayoutIndexTarGz :: RepoPath
  - repoLayoutIndexTar :: RepoPath
  - repoLayoutPkgTarGz :: PackageIdentifier -> RepoPath
  }
- hackageRepoLayout :: RepoLayout
- cabalLocalRepoLayout :: RepoLayout
- data Mirror = Mirror {
  - mirrorUrlBase :: URI
  - mirrorContent :: MirrorContent
  }
- data MirrorContent = MirrorFull
- type MirrorDescription = String
- describeMirror :: Mirror -> MirrorDescription
- data RepoRoot
- type RepoPath = Path RepoRoot
- anchorRepoPathLocally :: Path root -> RepoPath -> Path root
- anchorRepoPathRemotely :: Path Web -> RepoPath -> Path Web
- data IndexRoot
- type IndexPath = Path IndexRoot
- data CacheRoot
- type CachePath = Path CacheRoot
- anchorCachePath :: Path root -> CachePath -> Path root
- data Delegation = Delegation (Pattern a) (Replacement a)
- data RootRoles = RootRoles {
  - rootRolesRoot :: RoleSpec Root
  - rootRolesSnapshot :: RoleSpec Snapshot
  - rootRolesTargets :: RoleSpec Targets
  - rootRolesTimestamp :: RoleSpec Timestamp
  - rootRolesMirrors :: RoleSpec Mirrors
  }
- data RoleSpec a = RoleSpec {
  - roleSpecKeys :: [Some PublicKey]
  - roleSpecThreshold :: KeyThreshold
  }
- newtype Signatures = Signatures [Signature]
- unsigned :: a -> Signed a
- withSignatures :: ToJSON WriteJSON a => RepoLayout -> [Some Key] -> a -> Signed a
- withSignatures' :: ToJSON Identity a => [Some Key] -> a -> Signed a
- signRendered :: [Some Key] -> ByteString -> Signatures
- verifySignature :: ByteString -> Signature -> Bool
- signedFromJSON :: (MonadKeys m, FromJSON m a) => JSValue -> m (Signed a)
- verifySignatures :: JSValue -> Signatures -> Bool
- data UninterpretedSignatures a = UninterpretedSignatures {
  - uninterpretedSigned :: a
  - uninterpretedSignatures :: [PreSignature]
  }
- data PreSignature = PreSignature {
  - presignature :: ByteString
  - presigMethod :: Some KeyType
  - presigKeyId :: KeyId
  }
- fromPreSignature :: MonadKeys m => PreSignature -> m Signature
- fromPreSignatures :: MonadKeys m => [PreSignature] -> m Signatures
- toPreSignature :: Signature -> PreSignature
- toPreSignatures :: Signatures -> [PreSignature]
- data Delegations = Delegations {
  - delegationsKeys :: KeyEnv
  - delegationsRoles :: [DelegationSpec]
  }
- data DelegationSpec = DelegationSpec {
  - delegationSpecKeys :: [Some PublicKey]
  - delegationSpecThreshold :: KeyThreshold
  - delegation :: Delegation
  }
- targetsLookup :: TargetPath -> Targets -> Maybe FileInfo
- data Key a where
  - KeyEd25519 :: PublicKey -> SecretKey -> Key Ed25519
- sign :: PrivateKey typ -> ByteString -> ByteString
- data PublicKey a where
  - PublicKeyEd25519 :: PublicKey -> PublicKey Ed25519
- verify :: PublicKey typ -> ByteString -> ByteString -> Bool
- data Ed25519
- data PrivateKey a where
  - PrivateKeyEd25519 :: SecretKey -> PrivateKey Ed25519
- data KeyType typ where
  - KeyTypeEd25519 :: KeyType Ed25519
- somePublicKey :: Some Key -> Some PublicKey
- somePublicKeyType :: Some PublicKey -> Some KeyType
- someKeyId :: forall (key :: Type -> Type). HasKeyId key => Some key -> KeyId
- publicKey :: Key a -> PublicKey a
- privateKey :: Key a -> PrivateKey a
- createKey :: KeyType key -> IO (Key key)
- createKey' :: KeyType key -> IO (Some Key)
- newtype KeyId = KeyId {
  - keyIdString :: String
  }
- class HasKeyId (key :: Type -> Type) where
  - keyId :: key typ -> KeyId
- trusted :: Trusted a -> a
- data Repository (down :: Type -> Type)
- class DownloadedFile (down :: Type -> Type) where
  - downloadedVerify :: down a -> Trusted FileInfo -> IO Bool
  - downloadedRead :: down Metadata -> IO ByteString
  - downloadedCopyTo :: down a -> Path Absolute -> IO ()
- data SomeRemoteError where
  - SomeRemoteError :: forall e. Exception e => e -> SomeRemoteError
- data LogMessage
  - = LogRootUpdated
  - | LogVerificationError VerificationError
  - | LogDownloading (RemoteFile fs typ)
  - | LogUpdating (RemoteFile fs Binary)
  - | LogSelectedMirror MirrorDescription
  - | LogCannotUpdate (RemoteFile fs Binary) UpdateFailure
  - | LogMirrorFailed MirrorDescription SomeException
  - | LogLockWait (Path Absolute)
  - | LogLockWaitDone (Path Absolute)
  - | LogUnlock (Path Absolute)
- uncheckClientErrors :: ((Throws VerificationError, Throws SomeRemoteError, Throws InvalidPackageException) => IO a) -> IO a
- data VerificationError
  - = VerificationErrorSignatures TargetPath Integer [KeyId] [KeyId]
  - | VerificationErrorExpired TargetPath
  - | VerificationErrorVersion TargetPath
  - | VerificationErrorFileInfo TargetPath
  - | VerificationErrorUnknownTarget TargetPath
  - | VerificationErrorMissingSHA256 TargetPath
  - | VerificationErrorDeserialization TargetPath DeserializationError
  - | VerificationErrorLoop VerificationHistory
- type VerificationHistory = [Either RootUpdated VerificationError]
- data RootUpdated = RootUpdated
- data InvalidPackageException = InvalidPackageException PackageIdentifier
- data InvalidFileInIndex = InvalidFileInIndex {
  - invalidFileInIndex :: IndexFile dec
  - invalidFileInIndexRaw :: ByteString
  - invalidFileInIndexError :: DeserializationError
  }
- data LocalFileCorrupted = LocalFileCorrupted DeserializationError

# Checking for updates

checkForUpdates #

Arguments

:: forall (down :: Type -> Type). (Throws VerificationError, Throws SomeRemoteError) |
=> Repository down |
-> Maybe UTCTime | To check expiry times against (if using)
-> IO HasUpdates |

Generic logic for checking if there are updates

This implements the logic described in Section 5.1, "The client application", of the TUF spec. It checks which of the server metadata has changed, and downloads all changed metadata to the local cache. (Metadata here refers both to the TUF security metadata as well as the Hackage package index.)

You should pass `Nothing` for the UTCTime _only_ under exceptional circumstances (such as when the main server is down for longer than the expiry dates used in the timestamp files on mirrors).

data HasUpdates #

Constructors

HasUpdates |
NoUpdates |

#### Instances

Instances details

Show HasUpdates # |
Instance details Defined in Hackage.Security.Client Methods showsPrec :: Int -> HasUpdates -> ShowS # show :: HasUpdates -> String # showList :: [HasUpdates] -> ShowS #
Eq HasUpdates # |
Instance details Defined in Hackage.Security.Client Methods (==) :: HasUpdates -> HasUpdates -> Bool # (/=) :: HasUpdates -> HasUpdates -> Bool #
Ord HasUpdates # |
Instance details Defined in Hackage.Security.Client Methods compare :: HasUpdates -> HasUpdates -> Ordering # (<) :: HasUpdates -> HasUpdates -> Bool # (<=) :: HasUpdates -> HasUpdates -> Bool # (>) :: HasUpdates -> HasUpdates -> Bool # (>=) :: HasUpdates -> HasUpdates -> Bool # max :: HasUpdates -> HasUpdates -> HasUpdates # min :: HasUpdates -> HasUpdates -> HasUpdates #

# Downloading targets

downloadPackage #

Arguments

:: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError, Throws InvalidPackageException) |
=> Repository down | Repository
-> PackageIdentifier | Package to download
-> Path Absolute | Destination (see also `downloadPackage'`)
-> IO () |

Download a package

downloadPackage' #

Arguments

:: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError, Throws InvalidPackageException) |
=> Repository down | Repository
-> PackageIdentifier | Package to download
-> FilePath | Destination
-> IO () |

Variation on `downloadPackage` that takes a FilePath instead.

# Access to the Hackage index

data Directory #

Index directory

Constructors

Directory |

Fields

- directoryFirst :: DirectoryEntry

  The first entry in the dictionary

- directoryNext :: DirectoryEntry

  The next available (i.e., one after last) directory entry

- directoryLookup :: forall dec. IndexFile dec -> Maybe DirectoryEntry

  Lookup an entry in the dictionary

  This is an efficient operation.

- directoryEntries :: [(DirectoryEntry, IndexPath, Maybe (Some IndexFile))]

  An enumeration of all entries

  This field is lazily constructed, so if you don't need it, it does not incur a performance overhead. Moreover, the `IndexFile` is also created lazily so if you only need the raw `IndexPath` there is no parsing overhead.

  The entries are ordered by `DirectoryEntry` so that the entries can efficiently be read in sequence.

  NOTE: This means that there are two ways to enumerate all entries in the tar file, since when lookup an entry using `indexLookupEntry` the `DirectoryEntry` of the next entry is also returned. However, this involves reading through the entire `tar` file. If you only need to read some files, it is significantly more efficient to enumerate the tar entries using `directoryEntries` instead and only call `indexLookupEntry` when required.

newtype DirectoryEntry #

Entry into the Hackage index.

Constructors

DirectoryEntry |

Fields

- directoryEntryBlockNo :: TarEntryOffset

  (Low-level) block number of the tar index entry

  Exposed for the benefit of clients who read the `.tar` file directly. For this reason also the `Show` and `Read` instances for `DirectoryEntry` just print and parse the underlying `TarEntryOffset`.

#### Instances

Instances details

Read DirectoryEntry # |
Instance details Defined in Hackage.Security.Client Methods readsPrec :: Int -> ReadS DirectoryEntry # readList :: ReadS [DirectoryEntry] # readPrec :: ReadPrec DirectoryEntry # readListPrec :: ReadPrec [DirectoryEntry] #
Show DirectoryEntry # |
Instance details Defined in Hackage.Security.Client Methods showsPrec :: Int -> DirectoryEntry -> ShowS # show :: DirectoryEntry -> String # showList :: [DirectoryEntry] -> ShowS #
Eq DirectoryEntry # |
Instance details Defined in Hackage.Security.Client Methods (==) :: DirectoryEntry -> DirectoryEntry -> Bool # (/=) :: DirectoryEntry -> DirectoryEntry -> Bool #
Ord DirectoryEntry # |

Instance details

Defined in Hackage.Security.Client

Methods

compare :: DirectoryEntry -> DirectoryEntry -> Ordering #

(<) :: DirectoryEntry -> DirectoryEntry -> Bool #

(<=) :: DirectoryEntry -> DirectoryEntry -> Bool #

(>) :: DirectoryEntry -> DirectoryEntry -> Bool #

(>=) :: DirectoryEntry -> DirectoryEntry -> Bool #

max :: DirectoryEntry -> DirectoryEntry -> DirectoryEntry #

min :: DirectoryEntry -> DirectoryEntry -> DirectoryEntry #

getDirectory :: forall (down :: Type -> Type). Repository down -> IO Directory #

Read the Hackage index directory

Should only be called after `checkForUpdates`.

data IndexFile a where #

Files that we might request from the index

The type index tells us the type of the decoded file, if any. For files for which the library does not support decoding this will be `()`. NOTE: Clients should NOT rely on this type index being `()`, or they might break if we add support for parsing additional file formats in the future.

TODO: If we wanted to support legacy Hackage, we should also have a case for the global preferred-versions file. But supporting legacy Hackage will probably require more work anyway..

Constructors

IndexPkgMetadata :: PackageIdentifier -> IndexFile (Signed Targets) |
IndexPkgCabal :: PackageIdentifier -> IndexFile () |
IndexPkgPrefs :: PackageName -> IndexFile () |

#### Instances

Instances details

SomePretty IndexFile # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods somePretty :: DictPretty (IndexFile a) #
SomeShow IndexFile # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods someShow :: DictShow (IndexFile a) #
Show (IndexFile dec) # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods showsPrec :: Int -> IndexFile dec -> ShowS # show :: IndexFile dec -> String # showList :: [IndexFile dec] -> ShowS #
Pretty (IndexFile dec) # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods pretty :: IndexFile dec -> String #

data IndexEntry dec #

Entry from the Hackage index; see `withIndex`.

Constructors

IndexEntry |

Fields

- indexEntryPath :: IndexPath

  The raw path in the tarfile

- indexEntryPathParsed :: Maybe (IndexFile dec)

  The parsed file (if recognised)

- indexEntryContent :: ByteString

  The raw contents

  Although this is a lazy bytestring, this is actually read into memory strictly (i.e., it can safely be used outside the scope of withIndex and friends).

- indexEntryContentParsed :: Either SomeException dec

  The parsed contents

  This field is lazily constructed; the parser is not unless you do a pattern match on this value.

- indexEntryTime :: EpochTime

  The time of the entry in the tarfile.

data IndexCallbacks #

Various operations that we can perform on the index once its open

Note that `IndexEntry` contains a fields both for the raw file contents and the parsed file contents; clients can choose which to use.

In principle these callbacks will do verification (once we have implemented author signing). Right now they don't need to do that, because the index as a whole will have been verified.

Constructors

IndexCallbacks |

Fields

- indexLookupEntry :: DirectoryEntry -> IO (Some IndexEntry, Maybe DirectoryEntry)

  Look up an entry by `DirectoryEntry`

  Since these `DirectoryEntry`s must come from somewhere (probably from the `Directory`), it is assumed that they are valid; if they are not, an (unchecked) exception will be thrown.

  This function also returns the `DirectoryEntry` of the next file in the index (if any) for the benefit of clients who wish to walk through the entire index.

- indexLookupFile :: forall dec. IndexFile dec -> IO (Maybe (IndexEntry dec))

  Look up an entry by `IndexFile`

  Returns `Nothing` if the `IndexFile` does not refer to an existing file.

- indexLookupFileEntry :: forall dec. DirectoryEntry -> IndexFile dec -> IO (IndexEntry dec)

  Variation if both the `DirectoryEntry` and the `IndexFile` are known

  You might use this when scanning the index using `directoryEntries`.

- indexLookupCabal :: Throws InvalidPackageException => PackageIdentifier -> IO (Trusted ByteString)

  Get (raw) cabal file (wrapper around `indexLookupFile`)

- indexLookupMetadata :: Throws InvalidPackageException => PackageIdentifier -> IO (Trusted Targets)

  Lookup package metadata (wrapper around `indexLookupFile`)

  This will throw an (unchecked) exception if the `targets.json` file could not be parsed.

- indexLookupFileInfo :: (Throws InvalidPackageException, Throws VerificationError) => PackageIdentifier -> IO (Trusted FileInfo)

  Get file info (including hash) (wrapper around `indexLookupFile`)

- indexLookupHash :: (Throws InvalidPackageException, Throws VerificationError) => PackageIdentifier -> IO (Trusted Hash)

  Get the SHA256 hash for a package (wrapper around `indexLookupInfo`)

  In addition to the exceptions thrown by `indexLookupInfo`, this will also throw an exception if the SHA256 is not listed in the `FileMap` (again, this will not happen with a well-formed Hackage index.)

- indexDirectory :: Directory

  The `Directory` for the index

  We provide this here because `withIndex` will have read this anyway.

withIndex :: forall (down :: Type -> Type) a. Repository down -> (IndexCallbacks -> IO a) -> IO a #

Look up entries in the Hackage index

This is in `withFile` style so that clients can efficiently look up multiple files from the index.

Should only be called after `checkForUpdates`.

# Bootstrapping

requiresBootstrap :: forall (down :: Type -> Type). Repository down -> IO Bool #

Check if we need to bootstrap (i.e., if we have root info)

bootstrap :: forall (down :: Type -> Type). (Throws SomeRemoteError, Throws VerificationError) => Repository down -> [KeyId] -> KeyThreshold -> IO () #

Bootstrap the chain of trust

New clients might need to obtain a copy of the root metadata. This however represents a chicken-and-egg problem: how can we verify the root metadata we downloaded? The only possibility is to be provided with a set of an out-of-band set of root keys and an appropriate threshold.

Clients who provide a threshold of 0 can do an initial "unsafe" update of the root information, if they wish.

The downloaded root information will _only_ be verified against the provided keys, and _not_ against previously downloaded root info (if any). It is the responsibility of the client to call `bootstrap` only when this is the desired behaviour.

# Re-exports

data Signed a #

Constructors

Signed |

Fields

- signed :: a
- signatures :: Signatures

#### Instances

Instances details

MonadKeys m => FromJSON m (Signed Mirrors) # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fromJSON :: JSValue -> m (Signed Mirrors) #
MonadKeys m => FromJSON m (Signed Root) # | We give an instance for Signed Root rather than Root because the key environment from the root data is necessary to resolve the explicit sharing in the signatures.
Instance details Defined in Hackage.Security.TUF.Root Methods fromJSON :: JSValue -> m (Signed Root) #
(MonadKeys m, MonadReader RepoLayout m) => FromJSON m (Signed Snapshot) # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods fromJSON :: JSValue -> m (Signed Snapshot) #
MonadKeys m => FromJSON m (Signed Targets) # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fromJSON :: JSValue -> m (Signed Targets) #
(MonadKeys m, MonadReader RepoLayout m) => FromJSON m (Signed Timestamp) # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods fromJSON :: JSValue -> m (Signed Timestamp) #
(Monad m, ToJSON m a) => ToJSON m (Signed a) # |
Instance details Defined in Hackage.Security.TUF.Signed Methods toJSON :: Signed a -> m JSValue #

data Signature #

Constructors

Signature |

Fields

- signature :: ByteString
- signatureKey :: Some PublicKey

data IndexFile a where #

Files that we might request from the index

The type index tells us the type of the decoded file, if any. For files for which the library does not support decoding this will be `()`. NOTE: Clients should NOT rely on this type index being `()`, or they might break if we add support for parsing additional file formats in the future.

TODO: If we wanted to support legacy Hackage, we should also have a case for the global preferred-versions file. But supporting legacy Hackage will probably require more work anyway..

Constructors

IndexPkgMetadata :: PackageIdentifier -> IndexFile (Signed Targets) |
IndexPkgCabal :: PackageIdentifier -> IndexFile () |
IndexPkgPrefs :: PackageName -> IndexFile () |

#### Instances

Instances details

SomePretty IndexFile # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods somePretty :: DictPretty (IndexFile a) #
SomeShow IndexFile # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods someShow :: DictShow (IndexFile a) #
Show (IndexFile dec) # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods showsPrec :: Int -> IndexFile dec -> ShowS # show :: IndexFile dec -> String # showList :: [IndexFile dec] -> ShowS #
Pretty (IndexFile dec) # |
Instance details Defined in Hackage.Security.TUF.Layout.Index Methods pretty :: IndexFile dec -> String #

data FileMap #

Mapping from paths to file info

File maps are used in target files; the paths are relative to the location of the target files containing the file map.

#### Instances

Instances details

Show FileMap # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods showsPrec :: Int -> FileMap -> ShowS # show :: FileMap -> String # showList :: [FileMap] -> ShowS #
ReportSchemaErrors m => FromJSON m FileMap # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods fromJSON :: JSValue -> m FileMap #
Monad m => ToJSON m FileMap # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods toJSON :: FileMap -> m JSValue #

data TargetPath #

Entries in `FileMap` either talk about the repository or the index

Constructors

TargetPathRepo RepoPath |
TargetPathIndex IndexPath |

#### Instances

Instances details

Show TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods showsPrec :: Int -> TargetPath -> ShowS # show :: TargetPath -> String # showList :: [TargetPath] -> ShowS #
Eq TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods (==) :: TargetPath -> TargetPath -> Bool # (/=) :: TargetPath -> TargetPath -> Bool #
Ord TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods compare :: TargetPath -> TargetPath -> Ordering # (<) :: TargetPath -> TargetPath -> Bool # (<=) :: TargetPath -> TargetPath -> Bool # (>) :: TargetPath -> TargetPath -> Bool # (>=) :: TargetPath -> TargetPath -> Bool # max :: TargetPath -> TargetPath -> TargetPath # min :: TargetPath -> TargetPath -> TargetPath #
Pretty TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods pretty :: TargetPath -> String #
ReportSchemaErrors m => FromObjectKey m TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods fromObjectKey :: String -> m (Maybe TargetPath) #
Monad m => ToObjectKey m TargetPath # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods toObjectKey :: TargetPath -> m String #

data FileChange #

Constructors

FileChanged FileInfo | File got added or modified; we record the new file info
FileDeleted | File got deleted

#### Instances

Instances details

Show FileChange # |
Instance details Defined in Hackage.Security.TUF.FileMap Methods showsPrec :: Int -> FileChange -> ShowS # show :: FileChange -> String # showList :: [FileChange] -> ShowS #

fileMapChanges #

Arguments

:: FileMap | Old
-> FileMap | New
-> Map TargetPath FileChange |

data FileInfo #

File information

This intentionally does not have an `Eq` instance; see `knownFileInfoEqual` and `verifyFileInfo` instead.

NOTE: Throughout we compute file information always over the raw bytes. For example, when `timestamp.json` lists the hash of `snapshot.json`, this hash is computed over the actual `snapshot.json` file (as opposed to the canonical form of the embedded JSON). This brings it in line with the hash computed over target files, where that is the only choice available.

Constructors

FileInfo |

Fields

- fileInfoLength :: FileLength
- fileInfoHashes :: Map HashFn Hash

#### Instances

Instances details

Show FileInfo # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods showsPrec :: Int -> FileInfo -> ShowS # show :: FileInfo -> String # showList :: [FileInfo] -> ShowS #
ReportSchemaErrors m => FromJSON m FileInfo # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods fromJSON :: JSValue -> m FileInfo #
Monad m => ToJSON m FileInfo # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods toJSON :: FileInfo -> m JSValue #

data Int54 #

54-bit integer values

JavaScript can only safely represent numbers between `-(2^53 - 1)` and `2^53 - 1`.

TODO: Although we introduce the type here, we don't actually do any bounds checking and just inherit all type class instance from Int64. We should probably define `fromInteger` to do bounds checking, give different instances for type classes such as `Bounded` and `FiniteBits`, etc.

#### Instances

Instances details

Data Int54 # |

Instance details

Defined in Text.JSON.Canonical

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Int54 -> c Int54 #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Int54 #

toConstr :: Int54 -> Constr #

dataTypeOf :: Int54 -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Int54) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Int54) #

gmapT :: (forall b. Data b => b -> b) -> Int54 -> Int54 #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Int54 -> r #

gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Int54 -> r #

gmapQ :: (forall d. Data d => d -> u) -> Int54 -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Int54 -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Int54 -> m Int54 #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Int54 -> m Int54 #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Int54 -> m Int54 #

Storable Int54 # |
Instance details Defined in Text.JSON.Canonical Methods sizeOf :: Int54 -> Int # alignment :: Int54 -> Int # peekElemOff :: Ptr Int54 -> Int -> IO Int54 # pokeElemOff :: Ptr Int54 -> Int -> Int54 -> IO () # peekByteOff :: Ptr b -> Int -> IO Int54 # pokeByteOff :: Ptr b -> Int -> Int54 -> IO () # peek :: Ptr Int54 -> IO Int54 # poke :: Ptr Int54 -> Int54 -> IO () #
Bits Int54 # |

Instance details

Defined in Text.JSON.Canonical

Methods

(.&.) :: Int54 -> Int54 -> Int54 #

(.|.) :: Int54 -> Int54 -> Int54 #

xor :: Int54 -> Int54 -> Int54 #

complement :: Int54 -> Int54 #

shift :: Int54 -> Int -> Int54 #

rotate :: Int54 -> Int -> Int54 #

zeroBits :: Int54 #

bit :: Int -> Int54 #

setBit :: Int54 -> Int -> Int54 #

clearBit :: Int54 -> Int -> Int54 #

complementBit :: Int54 -> Int -> Int54 #

testBit :: Int54 -> Int -> Bool #

bitSizeMaybe :: Int54 -> Maybe Int #

bitSize :: Int54 -> Int #

isSigned :: Int54 -> Bool #

shiftL :: Int54 -> Int -> Int54 #

unsafeShiftL :: Int54 -> Int -> Int54 #

shiftR :: Int54 -> Int -> Int54 #

unsafeShiftR :: Int54 -> Int -> Int54 #

rotateL :: Int54 -> Int -> Int54 #

rotateR :: Int54 -> Int -> Int54 #

popCount :: Int54 -> Int #

FiniteBits Int54 # |
Instance details Defined in Text.JSON.Canonical Methods finiteBitSize :: Int54 -> Int # countLeadingZeros :: Int54 -> Int # countTrailingZeros :: Int54 -> Int #
Bounded Int54 # |
Instance details Defined in Text.JSON.Canonical Methods minBound :: Int54 # maxBound :: Int54 #
Enum Int54 # |
Instance details Defined in Text.JSON.Canonical Methods succ :: Int54 -> Int54 # pred :: Int54 -> Int54 # toEnum :: Int -> Int54 # fromEnum :: Int54 -> Int # enumFrom :: Int54 -> [Int54] # enumFromThen :: Int54 -> Int54 -> [Int54] # enumFromTo :: Int54 -> Int54 -> [Int54] # enumFromThenTo :: Int54 -> Int54 -> Int54 -> [Int54] #
Ix Int54 # |
Instance details Defined in Text.JSON.Canonical Methods range :: (Int54, Int54) -> [Int54] # index :: (Int54, Int54) -> Int54 -> Int # unsafeIndex :: (Int54, Int54) -> Int54 -> Int # inRange :: (Int54, Int54) -> Int54 -> Bool # rangeSize :: (Int54, Int54) -> Int # unsafeRangeSize :: (Int54, Int54) -> Int #
Num Int54 # |
Instance details Defined in Text.JSON.Canonical Methods (+) :: Int54 -> Int54 -> Int54 # (-) :: Int54 -> Int54 -> Int54 # (*) :: Int54 -> Int54 -> Int54 # negate :: Int54 -> Int54 # abs :: Int54 -> Int54 # signum :: Int54 -> Int54 # fromInteger :: Integer -> Int54 #
Read Int54 # |
Instance details Defined in Text.JSON.Canonical Methods readsPrec :: Int -> ReadS Int54 # readList :: ReadS [Int54] # readPrec :: ReadPrec Int54 # readListPrec :: ReadPrec [Int54] #
Integral Int54 # |
Instance details Defined in Text.JSON.Canonical Methods quot :: Int54 -> Int54 -> Int54 # rem :: Int54 -> Int54 -> Int54 # div :: Int54 -> Int54 -> Int54 # mod :: Int54 -> Int54 -> Int54 # quotRem :: Int54 -> Int54 -> (Int54, Int54) # divMod :: Int54 -> Int54 -> (Int54, Int54) # toInteger :: Int54 -> Integer #
Real Int54 # |
Instance details Defined in Text.JSON.Canonical Methods toRational :: Int54 -> Rational #
Show Int54 # |
Instance details Defined in Text.JSON.Canonical Methods showsPrec :: Int -> Int54 -> ShowS # show :: Int54 -> String # showList :: [Int54] -> ShowS #
PrintfArg Int54 # |
Instance details Defined in Text.JSON.Canonical Methods formatArg :: Int54 -> FieldFormatter # parseFormat :: Int54 -> ModifierParser #
Eq Int54 # |
Instance details Defined in Text.JSON.Canonical Methods (==) :: Int54 -> Int54 -> Bool # (/=) :: Int54 -> Int54 -> Bool #
Ord Int54 # |
Instance details Defined in Text.JSON.Canonical Methods compare :: Int54 -> Int54 -> Ordering # (<) :: Int54 -> Int54 -> Bool # (<=) :: Int54 -> Int54 -> Bool # (>) :: Int54 -> Int54 -> Bool # (>=) :: Int54 -> Int54 -> Bool # max :: Int54 -> Int54 -> Int54 # min :: Int54 -> Int54 -> Int54 #
ReportSchemaErrors m => FromJSON m Int54 # |
Instance details Defined in Hackage.Security.Util.JSON Methods fromJSON :: JSValue -> m Int54 #
Monad m => ToJSON m Int54 # |
Instance details Defined in Hackage.Security.Util.JSON Methods toJSON :: Int54 -> m JSValue #

data Header #

Occasionally it is useful to read only a header from a file.

`HeaderOnly` intentionally only has a `FromJSON` instance (no `ToJSON`).

Constructors

Header |

Fields

- headerExpires :: FileExpires
- headerVersion :: FileVersion

#### Instances

Instances details

HasHeader Header # |
Instance details Defined in Hackage.Security.TUF.Header Methods fileExpires :: Lens' Header FileExpires # fileVersion :: Lens' Header FileVersion #
ReportSchemaErrors m => FromJSON m Header # |
Instance details Defined in Hackage.Security.TUF.Header Methods fromJSON :: JSValue -> m Header #

data Mirrors #

Constructors

Mirrors |

Fields

- mirrorsVersion :: FileVersion
- mirrorsExpires :: FileExpires
- mirrorsMirrors :: [Mirror]

#### Instances

Instances details

HasHeader Mirrors # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fileExpires :: Lens' Mirrors FileExpires # fileVersion :: Lens' Mirrors FileVersion #
VerifyRole Mirrors # |
Instance details Defined in Hackage.Security.Trusted Methods verifyRole :: Trusted Root -> TargetPath -> Maybe FileVersion -> Maybe UTCTime -> Signed Mirrors -> Either VerificationError (SignaturesVerified Mirrors) #
(MonadError DeserializationError m, ReportSchemaErrors m) => FromJSON m Mirrors # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fromJSON :: JSValue -> m Mirrors #
Monad m => ToJSON m Mirrors # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods toJSON :: Mirrors -> m JSValue #
MonadKeys m => FromJSON m (Signed Mirrors) # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fromJSON :: JSValue -> m (Signed Mirrors) #

data Root #

The root metadata

NOTE: We must have the invariant that ALL keys (apart from delegation keys) must be listed in `rootKeys`. (Delegation keys satisfy a similar invariant, see Targets.)

Constructors

Root |

Fields

- rootVersion :: FileVersion
- rootExpires :: FileExpires
- rootKeys :: KeyEnv
- rootRoles :: RootRoles

#### Instances

Instances details

HasHeader Root # |
Instance details Defined in Hackage.Security.TUF.Root Methods fileExpires :: Lens' Root FileExpires # fileVersion :: Lens' Root FileVersion #
VerifyRole Root # |
Instance details Defined in Hackage.Security.Trusted Methods verifyRole :: Trusted Root -> TargetPath -> Maybe FileVersion -> Maybe UTCTime -> Signed Root -> Either VerificationError (SignaturesVerified Root) #
Monad m => ToJSON m Root # |
Instance details Defined in Hackage.Security.TUF.Root Methods toJSON :: Root -> m JSValue #
MonadKeys m => FromJSON m (Signed Root) # | We give an instance for Signed Root rather than Root because the key environment from the root data is necessary to resolve the explicit sharing in the signatures.
Instance details Defined in Hackage.Security.TUF.Root Methods fromJSON :: JSValue -> m (Signed Root) #

data Snapshot #

Constructors

Snapshot |

Fields

- snapshotVersion :: FileVersion
- snapshotExpires :: FileExpires
- snapshotInfoRoot :: FileInfo

  File info for the root metadata

  We list this explicitly in the snapshot so that we can check if we need to update the root metadata without first having to download the entire index tarball.

- snapshotInfoMirrors :: FileInfo

  File info for the mirror metadata

- snapshotInfoTarGz :: FileInfo

  Compressed index tarball

- snapshotInfoTar :: Maybe FileInfo

  Uncompressed index tarball

  Repositories are not required to provide this.

#### Instances

Instances details

HasHeader Snapshot # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods fileExpires :: Lens' Snapshot FileExpires # fileVersion :: Lens' Snapshot FileVersion #
VerifyRole Snapshot # |
Instance details Defined in Hackage.Security.Trusted Methods verifyRole :: Trusted Root -> TargetPath -> Maybe FileVersion -> Maybe UTCTime -> Signed Snapshot -> Either VerificationError (SignaturesVerified Snapshot) #
(MonadReader RepoLayout m, MonadError DeserializationError m, ReportSchemaErrors m) => FromJSON m Snapshot # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods fromJSON :: JSValue -> m Snapshot #
MonadReader RepoLayout m => ToJSON m Snapshot # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods toJSON :: Snapshot -> m JSValue #
(MonadKeys m, MonadReader RepoLayout m) => FromJSON m (Signed Snapshot) # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods fromJSON :: JSValue -> m (Signed Snapshot) #

data Targets #

Target metadata

Most target files do not need expiry dates because they are not subject to change (and hence attacks like freeze attacks are not a concern).

Constructors

Targets |

Fields

- targetsVersion :: FileVersion
- targetsExpires :: FileExpires
- targetsTargets :: FileMap
- targetsDelegations :: Maybe Delegations

#### Instances

Instances details

Show Targets # |
Instance details Defined in Hackage.Security.TUF.Targets Methods showsPrec :: Int -> Targets -> ShowS # show :: Targets -> String # showList :: [Targets] -> ShowS #
HasHeader Targets # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fileExpires :: Lens' Targets FileExpires # fileVersion :: Lens' Targets FileVersion #
MonadKeys m => FromJSON m Targets # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fromJSON :: JSValue -> m Targets #
Monad m => ToJSON m Targets # |
Instance details Defined in Hackage.Security.TUF.Targets Methods toJSON :: Targets -> m JSValue #
MonadKeys m => FromJSON m (Signed Targets) # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fromJSON :: JSValue -> m (Signed Targets) #

data Timestamp #

Constructors

Timestamp |

Fields

- timestampVersion :: FileVersion
- timestampExpires :: FileExpires
- timestampInfoSnapshot :: FileInfo

#### Instances

Instances details

HasHeader Timestamp # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods fileExpires :: Lens' Timestamp FileExpires # fileVersion :: Lens' Timestamp FileVersion #
VerifyRole Timestamp # |
Instance details Defined in Hackage.Security.Trusted Methods verifyRole :: Trusted Root -> TargetPath -> Maybe FileVersion -> Maybe UTCTime -> Signed Timestamp -> Either VerificationError (SignaturesVerified Timestamp) #
(MonadReader RepoLayout m, MonadError DeserializationError m, ReportSchemaErrors m) => FromJSON m Timestamp # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods fromJSON :: JSValue -> m Timestamp #
MonadReader RepoLayout m => ToJSON m Timestamp # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods toJSON :: Timestamp -> m JSValue #
(MonadKeys m, MonadReader RepoLayout m) => FromJSON m (Signed Timestamp) # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods fromJSON :: JSValue -> m (Signed Timestamp) #

newtype FileLength #

File length

Having verified file length information means we can protect against endless data attacks and similar.

Constructors

FileLength |

Fields

- fileLength :: Int54

#### Instances

Instances details

Show FileLength # |
Instance details Defined in Hackage.Security.TUF.Common Methods showsPrec :: Int -> FileLength -> ShowS # show :: FileLength -> String # showList :: [FileLength] -> ShowS #
Eq FileLength # |
Instance details Defined in Hackage.Security.TUF.Common Methods (==) :: FileLength -> FileLength -> Bool # (/=) :: FileLength -> FileLength -> Bool #
Ord FileLength # |
Instance details Defined in Hackage.Security.TUF.Common Methods compare :: FileLength -> FileLength -> Ordering # (<) :: FileLength -> FileLength -> Bool # (<=) :: FileLength -> FileLength -> Bool # (>) :: FileLength -> FileLength -> Bool # (>=) :: FileLength -> FileLength -> Bool # max :: FileLength -> FileLength -> FileLength # min :: FileLength -> FileLength -> FileLength #
ReportSchemaErrors m => FromJSON m FileLength # |
Instance details Defined in Hackage.Security.TUF.Common Methods fromJSON :: JSValue -> m FileLength #
Monad m => ToJSON m FileLength # |
Instance details Defined in Hackage.Security.TUF.Common Methods toJSON :: FileLength -> m JSValue #

newtype Hash #

File hash

Constructors

Hash String |

#### Instances

Instances details

Show Hash # |
Instance details Defined in Hackage.Security.TUF.Common Methods showsPrec :: Int -> Hash -> ShowS # show :: Hash -> String # showList :: [Hash] -> ShowS #
Eq Hash # |
Instance details Defined in Hackage.Security.TUF.Common Methods (==) :: Hash -> Hash -> Bool # (/=) :: Hash -> Hash -> Bool #
Ord Hash # |
Instance details Defined in Hackage.Security.TUF.Common Methods compare :: Hash -> Hash -> Ordering # (<) :: Hash -> Hash -> Bool # (<=) :: Hash -> Hash -> Bool # (>) :: Hash -> Hash -> Bool # (>=) :: Hash -> Hash -> Bool # max :: Hash -> Hash -> Hash # min :: Hash -> Hash -> Hash #
ReportSchemaErrors m => FromJSON m Hash # |
Instance details Defined in Hackage.Security.TUF.Common Methods fromJSON :: JSValue -> m Hash #
Monad m => ToJSON m Hash # |
Instance details Defined in Hackage.Security.TUF.Common Methods toJSON :: Hash -> m JSValue #

newtype KeyThreshold #

Key threshold

The key threshold is the minimum number of keys a document must be signed with. Key thresholds are specified in `RoleSpec` or `DelegationsSpec`.

Constructors

KeyThreshold Int54 |

#### Instances

Instances details

Show KeyThreshold # |
Instance details Defined in Hackage.Security.TUF.Common Methods showsPrec :: Int -> KeyThreshold -> ShowS # show :: KeyThreshold -> String # showList :: [KeyThreshold] -> ShowS #
Eq KeyThreshold # |
Instance details Defined in Hackage.Security.TUF.Common Methods (==) :: KeyThreshold -> KeyThreshold -> Bool # (/=) :: KeyThreshold -> KeyThreshold -> Bool #
Ord KeyThreshold # |

Instance details

Defined in Hackage.Security.TUF.Common

Methods

compare :: KeyThreshold -> KeyThreshold -> Ordering #

(<) :: KeyThreshold -> KeyThreshold -> Bool #

(<=) :: KeyThreshold -> KeyThreshold -> Bool #

(>) :: KeyThreshold -> KeyThreshold -> Bool #

(>=) :: KeyThreshold -> KeyThreshold -> Bool #

max :: KeyThreshold -> KeyThreshold -> KeyThreshold #

min :: KeyThreshold -> KeyThreshold -> KeyThreshold #

ReportSchemaErrors m => FromJSON m KeyThreshold # |
Instance details Defined in Hackage.Security.TUF.Common Methods fromJSON :: JSValue -> m KeyThreshold #
Monad m => ToJSON m KeyThreshold # |
Instance details Defined in Hackage.Security.TUF.Common Methods toJSON :: KeyThreshold -> m JSValue #

data HashFn #

Constructors

HashFnSHA256 |
HashFnMD5 |

#### Instances

Instances details

Show HashFn # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods showsPrec :: Int -> HashFn -> ShowS # show :: HashFn -> String # showList :: [HashFn] -> ShowS #
Eq HashFn # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods (==) :: HashFn -> HashFn -> Bool # (/=) :: HashFn -> HashFn -> Bool #
Ord HashFn # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods compare :: HashFn -> HashFn -> Ordering # (<) :: HashFn -> HashFn -> Bool # (<=) :: HashFn -> HashFn -> Bool # (>) :: HashFn -> HashFn -> Bool # (>=) :: HashFn -> HashFn -> Bool # max :: HashFn -> HashFn -> HashFn # min :: HashFn -> HashFn -> HashFn #
ReportSchemaErrors m => FromObjectKey m HashFn # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods fromObjectKey :: String -> m (Maybe HashFn) #
Monad m => ToObjectKey m HashFn # |
Instance details Defined in Hackage.Security.TUF.FileInfo Methods toObjectKey :: HashFn -> m String #

fileInfo :: ByteString -> FileInfo #

Compute `FileInfo`

TODO: Currently this will load the entire input bytestring into memory. We need to make this incremental, by computing the length and all hashes in a single traversal over the input.

computeFileInfo :: FsRoot root => Path root -> IO FileInfo #

Compute `FileInfo`

compareTrustedFileInfo #

Arguments

:: FileInfo | expected (from trusted TUF files)
-> FileInfo | actual (from `fileInfo` on target file)
-> Bool |

Compare the expected trusted file info against the actual file info of a target file.

This should be used only when the `FileInfo` is already known. If we want to compare known `FileInfo` against a file on disk we should delay until we have confirmed that the file lengths match (see `downloadedVerify`).

knownFileInfoEqual :: FileInfo -> FileInfo -> Bool #

fileInfoSHA256 :: FileInfo -> Maybe Hash #

Extract SHA256 hash from `FileInfo` (if present)

class HasHeader a where #

Methods

fileExpires :: Lens' a FileExpires #

File expiry date

fileVersion :: Lens' a FileVersion #

File version (monotonically increasing counter)

#### Instances

Instances details

HasHeader Header # |
Instance details Defined in Hackage.Security.TUF.Header Methods fileExpires :: Lens' Header FileExpires # fileVersion :: Lens' Header FileVersion #
HasHeader Mirrors # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fileExpires :: Lens' Mirrors FileExpires # fileVersion :: Lens' Mirrors FileVersion #
HasHeader Root # |
Instance details Defined in Hackage.Security.TUF.Root Methods fileExpires :: Lens' Root FileExpires # fileVersion :: Lens' Root FileVersion #
HasHeader Snapshot # |
Instance details Defined in Hackage.Security.TUF.Snapshot Methods fileExpires :: Lens' Snapshot FileExpires # fileVersion :: Lens' Snapshot FileVersion #
HasHeader Targets # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fileExpires :: Lens' Targets FileExpires # fileVersion :: Lens' Targets FileVersion #
HasHeader Timestamp # |
Instance details Defined in Hackage.Security.TUF.Timestamp Methods fileExpires :: Lens' Timestamp FileExpires # fileVersion :: Lens' Timestamp FileVersion #

newtype FileVersion #

File version

The file version is a flat integer which must monotonically increase on every file update.

`Show` and `Read` instance are defined in terms of the underlying `Int` (this is used for example by Hackage during the backup process).

Constructors

FileVersion Int54 |

#### Instances

Instances details

Read FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods readsPrec :: Int -> ReadS FileVersion # readList :: ReadS [FileVersion] # readPrec :: ReadPrec FileVersion # readListPrec :: ReadPrec [FileVersion] #
Show FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods showsPrec :: Int -> FileVersion -> ShowS # show :: FileVersion -> String # showList :: [FileVersion] -> ShowS #
Eq FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods (==) :: FileVersion -> FileVersion -> Bool # (/=) :: FileVersion -> FileVersion -> Bool #
Ord FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods compare :: FileVersion -> FileVersion -> Ordering # (<) :: FileVersion -> FileVersion -> Bool # (<=) :: FileVersion -> FileVersion -> Bool # (>) :: FileVersion -> FileVersion -> Bool # (>=) :: FileVersion -> FileVersion -> Bool # max :: FileVersion -> FileVersion -> FileVersion # min :: FileVersion -> FileVersion -> FileVersion #
ReportSchemaErrors m => FromJSON m FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods fromJSON :: JSValue -> m FileVersion #
Monad m => ToJSON m FileVersion # |
Instance details Defined in Hackage.Security.TUF.Header Methods toJSON :: FileVersion -> m JSValue #

newtype FileExpires #

File expiry date

A `Nothing` value here means no expiry. That makes it possible to set some files to never expire. (Note that not having the Maybe in the type here still allows that, because you could set an expiry date 2000 years into the future. By having the Maybe here we avoid the _need_ for such encoding issues.)

Constructors

FileExpires (Maybe UTCTime) |

#### Instances

Instances details

Show FileExpires # |
Instance details Defined in Hackage.Security.TUF.Header Methods showsPrec :: Int -> FileExpires -> ShowS # show :: FileExpires -> String # showList :: [FileExpires] -> ShowS #
Eq FileExpires # |
Instance details Defined in Hackage.Security.TUF.Header Methods (==) :: FileExpires -> FileExpires -> Bool # (/=) :: FileExpires -> FileExpires -> Bool #
Ord FileExpires # |
Instance details Defined in Hackage.Security.TUF.Header Methods compare :: FileExpires -> FileExpires -> Ordering # (<) :: FileExpires -> FileExpires -> Bool # (<=) :: FileExpires -> FileExpires -> Bool # (>) :: FileExpires -> FileExpires -> Bool # (>=) :: FileExpires -> FileExpires -> Bool # max :: FileExpires -> FileExpires -> FileExpires # min :: FileExpires -> FileExpires -> FileExpires #
ReportSchemaErrors m => FromJSON m FileExpires # |
Instance details Defined in Hackage.Security.TUF.Header Methods fromJSON :: JSValue -> m FileExpires #
Monad m => ToJSON m FileExpires # |
Instance details Defined in Hackage.Security.TUF.Header Methods toJSON :: FileExpires -> m JSValue #

expiresInDays :: UTCTime -> Integer -> FileExpires #

expiresNever :: FileExpires #

isExpired :: UTCTime -> FileExpires -> Bool #

versionInitial :: FileVersion #

versionIncrement :: FileVersion -> FileVersion #

data CacheLayout #

Location of the various files we cache

Although the generic TUF algorithms do not care how we organize the cache, we nonetheless specify this here because as long as there are tools which access files in the cache directly we need to define the cache layout. See also comments for `defaultCacheLayout`.

Constructors

CacheLayout |

Fields

- cacheLayoutRoot :: CachePath

  TUF root metadata

- cacheLayoutTimestamp :: CachePath

  TUF timestamp

- cacheLayoutSnapshot :: CachePath

  TUF snapshot

- cacheLayoutMirrors :: CachePath

  TUF mirrors list

- cacheLayoutIndexTar :: CachePath

  Uncompressed index tarball

- cacheLayoutIndexIdx :: CachePath

  Index to the uncompressed index tarball

- cacheLayoutIndexTarGz :: CachePath

  Compressed index tarball

  We cache both the compressed and the uncompressed tarballs, because incremental updates happen through the compressed tarball, but reads happen through the uncompressed one (with the help of the tarball index).

cabalCacheLayout :: CacheLayout #

The cache layout cabal-install uses

We cache the index as `cache/00-index.tar`; this is important because `cabal-install` expects to find it there (and does not currently go through the hackage-security library to get files from the index).

data IndexLayout #

Layout of the files within the index tarball

Constructors

IndexLayout |

Fields

- indexFileToPath :: forall dec. IndexFile dec -> IndexPath

  Translate an `IndexFile` to a path

- indexFileFromPath :: IndexPath -> Maybe (Some IndexFile)

  Parse an `FilePath`

hackageIndexLayout :: IndexLayout #

The layout of the index as maintained on Hackage

indexLayoutPkgMetadata :: IndexLayout -> PackageIdentifier -> IndexPath #

indexLayoutPkgCabal :: IndexLayout -> PackageIdentifier -> IndexPath #

indexLayoutPkgPrefs :: IndexLayout -> PackageName -> IndexPath #

data RepoLayout #

Layout of a repository

Constructors

RepoLayout |

Fields

- repoLayoutRoot :: RepoPath

  TUF root metadata

- repoLayoutTimestamp :: RepoPath

  TUF timestamp

- repoLayoutSnapshot :: RepoPath

  TUF snapshot

- repoLayoutMirrors :: RepoPath

  TUF mirrors list

- repoLayoutIndexTarGz :: RepoPath

  Compressed index tarball

- repoLayoutIndexTar :: RepoPath

  Uncompressed index tarball

- repoLayoutPkgTarGz :: PackageIdentifier -> RepoPath

  Path to the package tarball

#### Instances

Instances details

MonadReader RepoLayout ReadJSON_Keys_Layout # |
Instance details Defined in Hackage.Security.JSON Methods ask :: ReadJSON_Keys_Layout RepoLayout # local :: (RepoLayout -> RepoLayout) -> ReadJSON_Keys_Layout a -> ReadJSON_Keys_Layout a # reader :: (RepoLayout -> a) -> ReadJSON_Keys_Layout a #
MonadReader RepoLayout WriteJSON # |
Instance details Defined in Hackage.Security.JSON Methods ask :: WriteJSON RepoLayout # local :: (RepoLayout -> RepoLayout) -> WriteJSON a -> WriteJSON a # reader :: (RepoLayout -> a) -> WriteJSON a #

hackageRepoLayout :: RepoLayout #

The layout used on Hackage

cabalLocalRepoLayout :: RepoLayout #

Layout used by cabal for ("legacy") local repos

Obviously, such repos do not normally contain any of the TUF files, so their location is more or less arbitrary here.

data Mirror #

Definition of a mirror

NOTE: Unlike the TUF specification, we require that all mirrors must have the same format. That is, we omit `metapath` and `targetspath`.

Constructors

Mirror |

Fields

- mirrorUrlBase :: URI
- mirrorContent :: MirrorContent

#### Instances

Instances details

Show Mirror # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods showsPrec :: Int -> Mirror -> ShowS # show :: Mirror -> String # showList :: [Mirror] -> ShowS #
ReportSchemaErrors m => FromJSON m Mirror # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods fromJSON :: JSValue -> m Mirror #
Monad m => ToJSON m Mirror # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods toJSON :: Mirror -> m JSValue #

data MirrorContent #

Full versus partial mirrors

The TUF spec explicitly allows for partial mirrors, with the mirrors file specifying (through patterns) what is available from partial mirrors.

For now we only support full mirrors; if we wanted to add partial mirrors, we would add a second `MirrorPartial` constructor here with arguments corresponding to TUF's `metacontent` and `targetscontent` fields.

Constructors

MirrorFull |

#### Instances

Instances details

Show MirrorContent # |
Instance details Defined in Hackage.Security.TUF.Mirrors Methods showsPrec :: Int -> MirrorContent -> ShowS # show :: MirrorContent -> String # showList :: [MirrorContent] -> ShowS #

type MirrorDescription = String #

describeMirror :: Mirror -> MirrorDescription #

Give a human-readable description of a particular mirror

(for use in error messages)

data RepoRoot #

The root of the repository

Repository roots can be anchored at a remote URL or a local directory.

Note that even for remote repos `RepoRoot` is (potentially) different from `Web` -- for a repository located at, say, `http://hackage.haskell.org` they happen to coincide, but for one location at `http://example.com/some/subdirectory` they do not.

#### Instances

Instances details

Pretty (Path RepoRoot) # |
Instance details Defined in Hackage.Security.TUF.Paths Methods pretty :: Path RepoRoot -> String #

type RepoPath = Path RepoRoot #

Paths relative to the root of the repository

anchorRepoPathLocally :: Path root -> RepoPath -> Path root #

anchorRepoPathRemotely :: Path Web -> RepoPath -> Path Web #

data IndexRoot #

The root of the index tarball

#### Instances

Instances details

Pretty (Path IndexRoot) # |
Instance details Defined in Hackage.Security.TUF.Paths Methods pretty :: Path IndexRoot -> String #

type IndexPath = Path IndexRoot #

Paths relative to the root of the index tarball

data CacheRoot #

The cache directory

#### Instances

Instances details

Pretty (Path CacheRoot) # |
Instance details Defined in Hackage.Security.TUF.Paths Methods pretty :: Path CacheRoot -> String #

type CachePath = Path CacheRoot #

anchorCachePath :: Path root -> CachePath -> Path root #

Anchor a cache path to the location of the cache

data Delegation #

A delegation

A delegation is a pair of a pattern and a replacement.

See `match` for an example.

Constructors

Delegation (Pattern a) (Replacement a) |

#### Instances

Instances details

Show Delegation # |
Instance details Defined in Hackage.Security.TUF.Patterns Methods showsPrec :: Int -> Delegation -> ShowS # show :: Delegation -> String # showList :: [Delegation] -> ShowS #
Lift Delegation # |
Instance details Defined in Hackage.Security.TUF.Patterns Methods lift :: Quote m => Delegation -> m Exp # liftTyped :: forall (m :: Type -> Type). Quote m => Delegation -> Code m Delegation #

data RootRoles #

Constructors

RootRoles |

Fields

- rootRolesRoot :: RoleSpec Root
- rootRolesSnapshot :: RoleSpec Snapshot
- rootRolesTargets :: RoleSpec Targets
- rootRolesTimestamp :: RoleSpec Timestamp
- rootRolesMirrors :: RoleSpec Mirrors

#### Instances

Instances details

MonadKeys m => FromJSON m RootRoles # |
Instance details Defined in Hackage.Security.TUF.Root Methods fromJSON :: JSValue -> m RootRoles #
Monad m => ToJSON m RootRoles # |
Instance details Defined in Hackage.Security.TUF.Root Methods toJSON :: RootRoles -> m JSValue #

data RoleSpec a #

Role specification

The phantom type indicates what kind of type this role is meant to verify.

Constructors

RoleSpec |

Fields

- roleSpecKeys :: [Some PublicKey]
- roleSpecThreshold :: KeyThreshold

#### Instances

Instances details

MonadKeys m => FromJSON m (RoleSpec a) # |
Instance details Defined in Hackage.Security.TUF.Root Methods fromJSON :: JSValue -> m (RoleSpec a) #
Monad m => ToJSON m (RoleSpec a) # |
Instance details Defined in Hackage.Security.TUF.Root Methods toJSON :: RoleSpec a -> m JSValue #
Show (RoleSpec a) # |
Instance details Defined in Hackage.Security.TUF.Root Methods showsPrec :: Int -> RoleSpec a -> ShowS # show :: RoleSpec a -> String # showList :: [RoleSpec a] -> ShowS #

newtype Signatures #

A list of signatures

Invariant: each signature must be made with a different key. We enforce this invariant for incoming untrusted data (`fromPreSignatures`) but not for lists of signatures that we create in code.

Constructors

Signatures [Signature] |

#### Instances

Instances details

MonadKeys m => FromJSON m Signatures # |
Instance details Defined in Hackage.Security.TUF.Signed Methods fromJSON :: JSValue -> m Signatures #
Monad m => ToJSON m Signatures # |
Instance details Defined in Hackage.Security.TUF.Signed Methods toJSON :: Signatures -> m JSValue #

unsigned :: a -> Signed a #

Create a new document without any signatures

withSignatures :: ToJSON WriteJSON a => RepoLayout -> [Some Key] -> a -> Signed a #

Sign a document

withSignatures' :: ToJSON Identity a => [Some Key] -> a -> Signed a #

Variation on `withSignatures` that doesn't need the repo layout

signRendered :: [Some Key] -> ByteString -> Signatures #

Construct signatures for already rendered value

verifySignature :: ByteString -> Signature -> Bool #

signedFromJSON :: (MonadKeys m, FromJSON m a) => JSValue -> m (Signed a) #

General FromJSON instance for signed datatypes

We don't give a general FromJSON instance for Signed because for some datatypes we need to do something special (datatypes where we need to read key environments); for instance, see the "Signed Root" instance.

verifySignatures :: JSValue -> Signatures -> Bool #

Signature verification

NOTES: 1. By definition, the signature must be verified against the canonical JSON format. This means we _must_ parse and then pretty print (as we do here) because the document as stored may or may not be in canonical format. 2. However, it is important that we NOT translate from the JSValue to whatever internal datatype we are using and then back to JSValue, because that may not roundtrip: we must allow for additional fields in the JSValue that we ignore (and would therefore lose when we attempt to roundtrip). 3. We verify that all signatures are valid, but we cannot verify (here) that these signatures are signed with the right key, or that we have a sufficient number of signatures. This will be the responsibility of the calling code.

data UninterpretedSignatures a #

File with uninterpreted signatures

Sometimes we want to be able to read a file without interpreting the signatures (that is, resolving the key IDs) or doing any kind of checks on them. One advantage of this is that this allows us to read many file types without any key environment at all, which is sometimes useful.

Constructors

UninterpretedSignatures |

Fields

- uninterpretedSigned :: a
- uninterpretedSignatures :: [PreSignature]

#### Instances

Instances details

(ReportSchemaErrors m, FromJSON m a) => FromJSON m (UninterpretedSignatures a) # |
Instance details Defined in Hackage.Security.TUF.Signed Methods fromJSON :: JSValue -> m (UninterpretedSignatures a) #
(Monad m, ToJSON m a) => ToJSON m (UninterpretedSignatures a) # |
Instance details Defined in Hackage.Security.TUF.Signed Methods toJSON :: UninterpretedSignatures a -> m JSValue #
Show a => Show (UninterpretedSignatures a) # |
Instance details Defined in Hackage.Security.TUF.Signed Methods showsPrec :: Int -> UninterpretedSignatures a -> ShowS # show :: UninterpretedSignatures a -> String # showList :: [UninterpretedSignatures a] -> ShowS #

data PreSignature #

A signature with a key ID (rather than an actual key)

This corresponds precisely to the TUF representation of a signature.

Constructors

PreSignature |

Fields

- presignature :: ByteString
- presigMethod :: Some KeyType
- presigKeyId :: KeyId

#### Instances

Instances details

Show PreSignature # |
Instance details Defined in Hackage.Security.TUF.Signed Methods showsPrec :: Int -> PreSignature -> ShowS # show :: PreSignature -> String # showList :: [PreSignature] -> ShowS #
ReportSchemaErrors m => FromJSON m PreSignature # |
Instance details Defined in Hackage.Security.TUF.Signed Methods fromJSON :: JSValue -> m PreSignature #
Monad m => ToJSON m PreSignature # |
Instance details Defined in Hackage.Security.TUF.Signed Methods toJSON :: PreSignature -> m JSValue #

fromPreSignature :: MonadKeys m => PreSignature -> m Signature #

Convert a pre-signature to a signature

Verifies that the key type matches the advertised method.

fromPreSignatures :: MonadKeys m => [PreSignature] -> m Signatures #

Convert a list of `PreSignature`s to a list of `Signature`s

This verifies the invariant that all signatures are made with different keys. We do this on the presignatures rather than the signatures so that we can do the check on key IDs, rather than keys (the latter don't have an Ord instance).

toPreSignature :: Signature -> PreSignature #

Convert signature to pre-signature

toPreSignatures :: Signatures -> [PreSignature] #

Convert list of pre-signatures to a list of signatures

data Delegations #

Delegations

Much like the Root datatype, this must have an invariant that ALL used keys (apart from the global keys, which are in the root key environment) must be listed in `delegationsKeys`.

Constructors

Delegations |

Fields

- delegationsKeys :: KeyEnv
- delegationsRoles :: [DelegationSpec]

#### Instances

Instances details

Show Delegations # |
Instance details Defined in Hackage.Security.TUF.Targets Methods showsPrec :: Int -> Delegations -> ShowS # show :: Delegations -> String # showList :: [Delegations] -> ShowS #
MonadKeys m => FromJSON m Delegations # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fromJSON :: JSValue -> m Delegations #
Monad m => ToJSON m Delegations # |
Instance details Defined in Hackage.Security.TUF.Targets Methods toJSON :: Delegations -> m JSValue #

data DelegationSpec #

Delegation specification

NOTE: This is a close analogue of `RoleSpec`.

Constructors

DelegationSpec |

Fields

- delegationSpecKeys :: [Some PublicKey]
- delegationSpecThreshold :: KeyThreshold
- delegation :: Delegation

#### Instances

Instances details

Show DelegationSpec # |
Instance details Defined in Hackage.Security.TUF.Targets Methods showsPrec :: Int -> DelegationSpec -> ShowS # show :: DelegationSpec -> String # showList :: [DelegationSpec] -> ShowS #
MonadKeys m => FromJSON m DelegationSpec # |
Instance details Defined in Hackage.Security.TUF.Targets Methods fromJSON :: JSValue -> m DelegationSpec #
Monad m => ToJSON m DelegationSpec # |
Instance details Defined in Hackage.Security.TUF.Targets Methods toJSON :: DelegationSpec -> m JSValue #

targetsLookup :: TargetPath -> Targets -> Maybe FileInfo #

data Key a where #

Constructors

KeyEd25519 :: PublicKey -> SecretKey -> Key Ed25519 |

#### Instances

Instances details

HasKeyId Key # |
Instance details Defined in Hackage.Security.Key Methods keyId :: Key typ -> KeyId #
SomeEq Key # |
Instance details Defined in Hackage.Security.Key Methods someEq :: DictEq (Key a) #
SomeShow Key # |
Instance details Defined in Hackage.Security.Key Methods someShow :: DictShow (Key a) #
ReportSchemaErrors m => FromJSON m (Some Key) # |
Instance details Defined in Hackage.Security.Key Methods fromJSON :: JSValue -> m (Some Key) #
Monad m => ToJSON m (Key typ) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: Key typ -> m JSValue #
Monad m => ToJSON m (Some Key) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: Some Key -> m JSValue #
Show (Key typ) # |
Instance details Defined in Hackage.Security.Key Methods showsPrec :: Int -> Key typ -> ShowS # show :: Key typ -> String # showList :: [Key typ] -> ShowS #
Eq (Key typ) # |
Instance details Defined in Hackage.Security.Key Methods (==) :: Key typ -> Key typ -> Bool # (/=) :: Key typ -> Key typ -> Bool #

sign :: PrivateKey typ -> ByteString -> ByteString #

Sign a bytestring and return the signature

TODO: It is unfortunate that we have to convert to a strict bytestring for ed25519

data PublicKey a where #

Constructors

PublicKeyEd25519 :: PublicKey -> PublicKey Ed25519 |

#### Instances

Instances details

HasKeyId PublicKey # |
Instance details Defined in Hackage.Security.Key Methods keyId :: PublicKey typ -> KeyId #
SomeEq PublicKey # |
Instance details Defined in Hackage.Security.Key Methods someEq :: DictEq (PublicKey a) #
SomeShow PublicKey # |
Instance details Defined in Hackage.Security.Key Methods someShow :: DictShow (PublicKey a) #
ReportSchemaErrors m => FromJSON m (Some PublicKey) # |
Instance details Defined in Hackage.Security.Key Methods fromJSON :: JSValue -> m (Some PublicKey) #
Monad m => ToJSON m (PublicKey typ) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: PublicKey typ -> m JSValue #
Monad m => ToJSON m (Some PublicKey) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: Some PublicKey -> m JSValue #
Show (PublicKey typ) # |
Instance details Defined in Hackage.Security.Key Methods showsPrec :: Int -> PublicKey typ -> ShowS # show :: PublicKey typ -> String # showList :: [PublicKey typ] -> ShowS #
Eq (PublicKey typ) # |
Instance details Defined in Hackage.Security.Key Methods (==) :: PublicKey typ -> PublicKey typ -> Bool # (/=) :: PublicKey typ -> PublicKey typ -> Bool #

verify :: PublicKey typ -> ByteString -> ByteString -> Bool #

data Ed25519 #

data PrivateKey a where #

Constructors

PrivateKeyEd25519 :: SecretKey -> PrivateKey Ed25519 |

#### Instances

Instances details

SomeEq PrivateKey # |
Instance details Defined in Hackage.Security.Key Methods someEq :: DictEq (PrivateKey a) #
SomeShow PrivateKey # |
Instance details Defined in Hackage.Security.Key Methods someShow :: DictShow (PrivateKey a) #
Show (PrivateKey typ) # |
Instance details Defined in Hackage.Security.Key Methods showsPrec :: Int -> PrivateKey typ -> ShowS # show :: PrivateKey typ -> String # showList :: [PrivateKey typ] -> ShowS #
Eq (PrivateKey typ) # |
Instance details Defined in Hackage.Security.Key Methods (==) :: PrivateKey typ -> PrivateKey typ -> Bool # (/=) :: PrivateKey typ -> PrivateKey typ -> Bool #

data KeyType typ where #

Constructors

KeyTypeEd25519 :: KeyType Ed25519 |

#### Instances

Instances details

SomeEq KeyType # |
Instance details Defined in Hackage.Security.Key Methods someEq :: DictEq (KeyType a) #
SomeShow KeyType # |
Instance details Defined in Hackage.Security.Key Methods someShow :: DictShow (KeyType a) #
ReportSchemaErrors m => FromJSON m (Some KeyType) # |
Instance details Defined in Hackage.Security.Key Methods fromJSON :: JSValue -> m (Some KeyType) #
Monad m => ToJSON m (KeyType typ) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: KeyType typ -> m JSValue #
Monad m => ToJSON m (Some KeyType) # |
Instance details Defined in Hackage.Security.Key Methods toJSON :: Some KeyType -> m JSValue #
Show (KeyType typ) # |
Instance details Defined in Hackage.Security.Key Methods showsPrec :: Int -> KeyType typ -> ShowS # show :: KeyType typ -> String # showList :: [KeyType typ] -> ShowS #
Eq (KeyType typ) # |
Instance details Defined in Hackage.Security.Key Methods (==) :: KeyType typ -> KeyType typ -> Bool # (/=) :: KeyType typ -> KeyType typ -> Bool #

somePublicKey :: Some Key -> Some PublicKey #

somePublicKeyType :: Some PublicKey -> Some KeyType #

someKeyId :: forall (key :: Type -> Type). HasKeyId key => Some key -> KeyId #

publicKey :: Key a -> PublicKey a #

privateKey :: Key a -> PrivateKey a #

createKey :: KeyType key -> IO (Key key) #

createKey' :: KeyType key -> IO (Some Key) #

newtype KeyId #

The key ID of a key, by definition, is the hexdigest of the SHA-256 hash of the canonical JSON form of the key where the private object key is excluded.

NOTE: The FromJSON and ToJSON instances for KeyId are intentionally omitted. Use writeKeyAsId instead.

Constructors

KeyId |

Fields

- keyIdString :: String

#### Instances

Instances details

Show KeyId # |
Instance details Defined in Hackage.Security.Key Methods showsPrec :: Int -> KeyId -> ShowS # show :: KeyId -> String # showList :: [KeyId] -> ShowS #
Eq KeyId # |
Instance details Defined in Hackage.Security.Key Methods (==) :: KeyId -> KeyId -> Bool # (/=) :: KeyId -> KeyId -> Bool #
Ord KeyId # |
Instance details Defined in Hackage.Security.Key Methods compare :: KeyId -> KeyId -> Ordering # (<) :: KeyId -> KeyId -> Bool # (<=) :: KeyId -> KeyId -> Bool # (>) :: KeyId -> KeyId -> Bool # (>=) :: KeyId -> KeyId -> Bool # max :: KeyId -> KeyId -> KeyId # min :: KeyId -> KeyId -> KeyId #
Monad m => FromObjectKey m KeyId # |
Instance details Defined in Hackage.Security.Key Methods fromObjectKey :: String -> m (Maybe KeyId) #
Monad m => ToObjectKey m KeyId # |
Instance details Defined in Hackage.Security.Key Methods toObjectKey :: KeyId -> m String #

class HasKeyId (key :: Type -> Type) where #

Compute the key ID of a key

Methods

keyId :: key typ -> KeyId #

#### Instances

Instances details

HasKeyId Key # |
Instance details Defined in Hackage.Security.Key Methods keyId :: Key typ -> KeyId #
HasKeyId PublicKey # |
Instance details Defined in Hackage.Security.Key Methods keyId :: PublicKey typ -> KeyId #

trusted :: Trusted a -> a #

## We only a few bits from .Repository

data Repository (down :: Type -> Type) #

Repository

This is an abstract representation of a repository. It simply provides a way to download metafiles and target files, without specifying how this is done. For instance, for a local repository this could just be doing a file read, whereas for remote repositories this could be using any kind of HTTP client.

#### Instances

Instances details

Show (Repository down) # |
Instance details Defined in Hackage.Security.Client.Repository Methods showsPrec :: Int -> Repository down -> ShowS # show :: Repository down -> String # showList :: [Repository down] -> ShowS #

class DownloadedFile (down :: Type -> Type) where #

Methods

downloadedVerify :: down a -> Trusted FileInfo -> IO Bool #

Verify a download file

downloadedRead :: down Metadata -> IO ByteString #

Read the file we just downloaded into memory

We never read binary data, only metadata.

downloadedCopyTo :: down a -> Path Absolute -> IO () #

Copy a downloaded file to its destination

#### Instances

Instances details

DownloadedFile LocalFile # |
Instance details Defined in Hackage.Security.Client.Repository.Local Methods downloadedVerify :: LocalFile a -> Trusted FileInfo -> IO Bool # downloadedRead :: LocalFile Metadata -> IO ByteString # downloadedCopyTo :: LocalFile a -> Path Absolute -> IO () #
DownloadedFile RemoteTemp # |
Instance details Defined in Hackage.Security.Client.Repository.Remote Methods downloadedVerify :: RemoteTemp a -> Trusted FileInfo -> IO Bool # downloadedRead :: RemoteTemp Metadata -> IO ByteString # downloadedCopyTo :: RemoteTemp a -> Path Absolute -> IO () #

data SomeRemoteError where #

Repository-specific exceptions

For instance, for repositories using HTTP this might correspond to a 404; for local repositories this might correspond to file-not-found, etc.

Constructors

SomeRemoteError :: forall e. Exception e => e -> SomeRemoteError |

#### Instances

Instances details

Exception SomeRemoteError # |
Instance details Defined in Hackage.Security.Client.Repository Methods toException :: SomeRemoteError -> SomeException # fromException :: SomeException -> Maybe SomeRemoteError # displayException :: SomeRemoteError -> String #
Show SomeRemoteError # |
Instance details Defined in Hackage.Security.Client.Repository Methods showsPrec :: Int -> SomeRemoteError -> ShowS # show :: SomeRemoteError -> String # showList :: [SomeRemoteError] -> ShowS #
Pretty SomeRemoteError # |
Instance details Defined in Hackage.Security.Client.Repository Methods pretty :: SomeRemoteError -> String #

data LogMessage #

Log messages

We use a `RemoteFile` rather than a `RepoPath` here because we might not have a `RepoPath` for the file that we were trying to download (that is, for example if the server does not provide an uncompressed tarball, it doesn't make much sense to list the path to that non-existing uncompressed tarball).

Constructors

LogRootUpdated | Root information was updated This message is issued when the root information is updated as part of the normal check for updates procedure. If the root information is updated because of a verification error WarningVerificationError is issued instead.
LogVerificationError VerificationError | A verification error Verification errors can be temporary, and may be resolved later; hence these are just warnings. (Verification errors that cannot be resolved are thrown as exceptions.)
LogDownloading (RemoteFile fs typ) | Download a file from a repository
LogUpdating (RemoteFile fs Binary) | Incrementally updating a file from a repository
LogSelectedMirror MirrorDescription | Selected a particular mirror
LogCannotUpdate (RemoteFile fs Binary) UpdateFailure | Updating a file failed (we will instead download it whole)
LogMirrorFailed MirrorDescription SomeException | We got an exception with a particular mirror (we will try with a different mirror if any are available)
LogLockWait (Path Absolute) | This log event is triggered before invoking a filesystem lock operation that may block for a significant amount of time; once the possibly blocking call completes successfully, `LogLockWaitDone` will be emitted. Since: 0.6.0
LogLockWaitDone (Path Absolute) | Denotes completion of the operation that advertised a `LogLockWait` event Since: 0.6.0
LogUnlock (Path Absolute) | Denotes the filesystem lock previously acquired (signaled by `LogLockWait`) has been released. Since: 0.6.0

#### Instances

Instances details

Pretty LogMessage # |
Instance details Defined in Hackage.Security.Client.Repository Methods pretty :: LogMessage -> String #

# Exceptions

uncheckClientErrors :: ((Throws VerificationError, Throws SomeRemoteError, Throws InvalidPackageException) => IO a) -> IO a #

Re-throw all exceptions thrown by the client API as unchecked exceptions

data VerificationError #

Errors thrown during role validation

Constructors

VerificationErrorSignatures TargetPath Integer [KeyId] [KeyId] | Not enough signatures signed with the appropriate keys
VerificationErrorExpired TargetPath | The file is expired
VerificationErrorVersion TargetPath | The file version is less than the previous version
VerificationErrorFileInfo TargetPath | File information mismatch
VerificationErrorUnknownTarget TargetPath | We tried to lookup file information about a particular target file, but the information wasn't in the corresponding `targets.json` file.
VerificationErrorMissingSHA256 TargetPath | The metadata for the specified target is missing a SHA256
VerificationErrorDeserialization TargetPath DeserializationError | Some verification errors materialize as deserialization errors For example: if we try to deserialize a timestamp file but the timestamp key has been rolled over, deserialization of the file will fail with `DeserializationErrorUnknownKey`.
VerificationErrorLoop VerificationHistory | The spec stipulates that if a verification error occurs during the check for updates, we must download new root information and start over. However, we limit how often we attempt this. We record all verification errors that occurred before we gave up.

#### Instances

Instances details

Exception VerificationError # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods toException :: VerificationError -> SomeException # fromException :: SomeException -> Maybe VerificationError # displayException :: VerificationError -> String #
Show VerificationError # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods showsPrec :: Int -> VerificationError -> ShowS # show :: VerificationError -> String # showList :: [VerificationError] -> ShowS #
Pretty VerificationError # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods pretty :: VerificationError -> String #

type VerificationHistory = [Either RootUpdated VerificationError] #

data RootUpdated #

Root metadata updated (as part of the normal update process)

Constructors

RootUpdated |

#### Instances

Instances details

Exception RootUpdated # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods toException :: RootUpdated -> SomeException # fromException :: SomeException -> Maybe RootUpdated # displayException :: RootUpdated -> String #
Show RootUpdated # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods showsPrec :: Int -> RootUpdated -> ShowS # show :: RootUpdated -> String # showList :: [RootUpdated] -> ShowS #
Pretty RootUpdated # |
Instance details Defined in Hackage.Security.Trusted.TCB Methods pretty :: RootUpdated -> String #

data InvalidPackageException #

Constructors

InvalidPackageException PackageIdentifier |

#### Instances

Instances details

Exception InvalidPackageException # |
Instance details Defined in Hackage.Security.Client Methods toException :: InvalidPackageException -> SomeException # fromException :: SomeException -> Maybe InvalidPackageException # displayException :: InvalidPackageException -> String #
Show InvalidPackageException # |
Instance details Defined in Hackage.Security.Client Methods showsPrec :: Int -> InvalidPackageException -> ShowS # show :: InvalidPackageException -> String # showList :: [InvalidPackageException] -> ShowS #
Pretty InvalidPackageException # |
Instance details Defined in Hackage.Security.Client Methods pretty :: InvalidPackageException -> String #

data InvalidFileInIndex #

Constructors

InvalidFileInIndex |

Fields

- invalidFileInIndex :: IndexFile dec
- invalidFileInIndexRaw :: ByteString
- invalidFileInIndexError :: DeserializationError

#### Instances

Instances details

Exception InvalidFileInIndex # |
Instance details Defined in Hackage.Security.Client Methods toException :: InvalidFileInIndex -> SomeException # fromException :: SomeException -> Maybe InvalidFileInIndex # displayException :: InvalidFileInIndex -> String #
Show InvalidFileInIndex # |
Instance details Defined in Hackage.Security.Client Methods showsPrec :: Int -> InvalidFileInIndex -> ShowS # show :: InvalidFileInIndex -> String # showList :: [InvalidFileInIndex] -> ShowS #
Pretty InvalidFileInIndex # |
Instance details Defined in Hackage.Security.Client Methods pretty :: InvalidFileInIndex -> String #

data LocalFileCorrupted #

Constructors

LocalFileCorrupted DeserializationError |

#### Instances

Instances details

Exception LocalFileCorrupted # |
Instance details Defined in Hackage.Security.Client Methods toException :: LocalFileCorrupted -> SomeException # fromException :: SomeException -> Maybe LocalFileCorrupted # displayException :: LocalFileCorrupted -> String #
Show LocalFileCorrupted # |
Instance details Defined in Hackage.Security.Client Methods showsPrec :: Int -> LocalFileCorrupted -> ShowS # show :: LocalFileCorrupted -> String # showList :: [LocalFileCorrupted] -> ShowS #
Pretty LocalFileCorrupted # |
Instance details Defined in Hackage.Security.Client Methods pretty :: LocalFileCorrupted -> String #