HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulehackage-security-0.6.3.2Haskell2010

Hackage.Security.Client

Main entry point into the Hackage Security framework for clients

  • 61 types
  • 3 classes
  • 52 values

Checking for updates

2 declarations
valuecheckForUpdates
  1. :: (Throws VerificationError, Throws SomeRemoteError)
  2. => Repository down
  3. -> Maybe UTCTime

    To check expiry times against (if using)

  4. -> 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).

Downloading targets

2 declarations

Access to the Hackage index

7 declarations
datadata Directory
#

Index directory

Constructors

newtypenewtype DirectoryEntry
#

Entry into the Hackage index.

Constructors

  • DirectoryEntry
    • 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.

Instances4Eq, Ord, Read, Show
datadata 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..

Instances4SomePretty, SomeShow, Show, Pretty
  • SomePretty IndexFileDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • SomeShow IndexFileDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • Show (IndexFile dec)Defined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • Pretty (IndexFile dec)Defined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
datadata IndexEntry dec
#

Entry from the Hackage index; see withIndex.

Constructors

datadata 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

Bootstrapping

2 declarations

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

92 declarations
datadata 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..

Instances4SomePretty, SomeShow, Show, Pretty
  • SomePretty IndexFileDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • SomeShow IndexFileDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • Show (IndexFile dec)Defined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
  • Pretty (IndexFile dec)Defined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Layout.Index
newtypenewtype 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.

Instances3Show, FromJSON, ToJSON
datadata TargetPath
#

Entries in FileMap either talk about the repository or the index

Instances6Eq, Ord, Show, Pretty, FromObjectKey, ToObjectKey
datadata 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.

Instances3Show, FromJSON, ToJSON
newtypenewtype 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.

Instances17Bounded, Enum, Eq, Integral, Data, Num, …
  • Bounded Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Enum Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Eq Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Integral Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Data Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Num Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Ord Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Read Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Real Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Show Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Ix Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Bits Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • FiniteBits Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • Storable Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • PrintfArg Int54Defined in hackage-security-0.6.3.2 · Text.JSON.Canonical
  • ReportSchemaErrors m => FromJSON m Int54Defined in hackage-security-0.6.3.2 · Hackage.Security.Util.JSON
  • Monad m => ToJSON m Int54Defined in hackage-security-0.6.3.2 · Hackage.Security.Util.JSON
datadata Mirrors
#
Instances5HasHeader, VerifyRole, ToJSON, FromJSON
datadata 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.)

Instances4HasHeader, VerifyRole, ToJSON, FromJSON
  • HasHeader RootDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Root
  • VerifyRole RootDefined in hackage-security-0.6.3.2 · Hackage.Security.Trusted
  • Monad m => ToJSON m RootDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Root
  • MonadKeys m => FromJSON m (Signed Root)Defined in hackage-security-0.6.3.2 · Hackage.Security.TUF.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.

datadata Signed a
#
Instances6FromJSON, ToJSON
datadata Snapshot
#

Constructors

Instances5HasHeader, VerifyRole, ToJSON, FromJSON
datadata 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).

Instances5Show, HasHeader, ToJSON, FromJSON
datadata Timestamp
#
Instances5HasHeader, VerifyRole, ToJSON, FromJSON
newtypenewtype FileLength
#

File length

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

Instances5Eq, Ord, Show, FromJSON, ToJSON
newtypenewtype Hash
#

File hash

Constructors

Instances5Eq, Ord, Show, FromJSON, ToJSON
  • Eq HashDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Common
  • Ord HashDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Common
  • Show HashDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Common
  • ReportSchemaErrors m => FromJSON m HashDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Common
  • Monad m => ToJSON m HashDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Common
newtypenewtype 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

Instances5Eq, Ord, Show, FromJSON, ToJSON
datadata HashFn
#
Instances5Eq, Ord, Show, FromObjectKey, ToObjectKey
  • Eq HashFnDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.FileInfo
  • Ord HashFnDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.FileInfo
  • Show HashFnDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.FileInfo
  • ReportSchemaErrors m => FromObjectKey m HashFnDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.FileInfo
  • Monad m => ToObjectKey m HashFnDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.FileInfo
valuefileInfo :: 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.

valuecompareTrustedFileInfo
  1. :: FileInfo

    expected (from trusted TUF files)

  2. -> FileInfo

    actual (from fileInfo on target file)

  3. -> 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).

classclass HasHeader a where
#

Methods

Instances6HasHeader
  • HasHeader HeaderDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Header
  • HasHeader MirrorsDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Mirrors
  • HasHeader RootDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Root
  • HasHeader SnapshotDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Snapshot
  • HasHeader TargetsDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Targets
  • HasHeader TimestampDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Timestamp
newtypenewtype 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

Instances6Eq, Ord, Read, Show, FromJSON, ToJSON
newtypenewtype 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

Instances5Eq, Ord, Show, FromJSON, ToJSON
datadata 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

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).

datadata RepoLayout
#

Layout of a repository

Constructors

Instances2MonadReader

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.

datadata 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.

Instances3Show, FromJSON, ToJSON
datadata 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.

Instances1Show
  • Show MirrorContentDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Mirrors
datadata IndexRoot
#

The root of the index tarball

Instances1Pretty
datadata CacheRoot
#

The cache directory

Instances1Pretty
datadata Delegation
#

A delegation

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

See match for an example.

Constructors

Instances2Show, Lift
  • Show DelegationDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Patterns
  • Lift DelegationDefined in hackage-security-0.6.3.2 · Hackage.Security.TUF.Patterns
datadata RoleSpec a
#

Role specification

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

Instances3FromJSON, ToJSON, Show
newtypenewtype 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

Instances2FromJSON, ToJSON
valueunsigned :: a -> Signed a
#

Create a new document without any signatures

valuesignedFromJSON :: (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.

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.

datadata 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.

Instances3FromJSON, ToJSON, Show
datadata PreSignature
#

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

This corresponds precisely to the TUF representation of a signature.

Instances3Show, FromJSON, ToJSON

Convert a list of PreSignatures to a list of Signatures

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).

datadata 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.

Instances3Show, FromJSON, ToJSON
datadata DelegationSpec
#

Delegation specification

NOTE: This is a close analogue of RoleSpec.

Instances3Show, FromJSON, ToJSON
datadata Key a where
#
Instances10HasKeyId, SomeEq, SomeShow, Typed, FromJSON, ToJSON, …
  • HasKeyId KeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • SomeEq KeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • SomeShow KeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Typed KeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • ReportSchemaErrors m => FromJSON m (Some Key)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => ToJSON m (Key typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => ToJSON m (Some Key)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Eq (Key typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Show (Key typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • type TypeOf Key = KeyTypeDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
datadata PublicKey a where
#
Instances10HasKeyId, SomeEq, SomeShow, Typed, FromJSON, ToJSON, …
datadata PrivateKey a where
#
Instances6SomeEq, SomeShow, Typed, Eq, Show, TypeOf
  • SomeEq PrivateKeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • SomeShow PrivateKeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Typed PrivateKeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Eq (PrivateKey typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Show (PrivateKey typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • type TypeOf PrivateKey = KeyTypeDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
datadata KeyType typ where
#
Instances8Unify, SomeEq, SomeShow, FromJSON, ToJSON, Eq, …
  • Unify KeyTypeDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • SomeEq KeyTypeDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • SomeShow KeyTypeDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • ReportSchemaErrors m => FromJSON m (Some KeyType)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => ToJSON m (KeyType typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => ToJSON m (Some KeyType)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Eq (KeyType typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Show (KeyType typ)Defined in hackage-security-0.6.3.2 · Hackage.Security.Key
newtypenewtype 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

Instances5Eq, Ord, Show, FromObjectKey, ToObjectKey
  • Eq KeyIdDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Ord KeyIdDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Show KeyIdDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => FromObjectKey m KeyIdDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • Monad m => ToObjectKey m KeyIdDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
classclass HasKeyId (key :: Type -> Type) where
#

Compute the key ID of a key

Methods

Instances2HasKeyId
  • HasKeyId KeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
  • HasKeyId PublicKeyDefined in hackage-security-0.6.3.2 · Hackage.Security.Key
valuesign :: 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

We only a few bits from .Repository

datadata 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.

Instances1Show
  • Show (Repository down)Defined in hackage-security-0.6.3.2 · Hackage.Security.Client.Repository
classclass DownloadedFile (down :: Type -> Type) where
#

Methods

Instances2DownloadedFile
datadata 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

Instances3Show, Exception, Pretty
datadata 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

Instances1Pretty
  • Pretty LogMessageDefined in hackage-security-0.6.3.2 · Hackage.Security.Client.Repository

Exceptions

7 declarations
datadata VerificationError
#

Errors thrown during role validation

Constructors

Instances3Show, Exception, Pretty
datadata RootUpdated
#

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

Instances3Show, Exception, Pretty