Edit on GitHub

model_signing.verifying

High level API for the verification interface of model_signing library.

This module supports configuring the verification method used to verify a model, before performing the verification.

model_signing.verifying.Config().use_sigstore_verifier(
    identity=identity, oidc_issuer=oidc_provider
).verify("finbert", "finbert.sig")

The same verification configuration can be used to verify multiple models:

verifying_config = model_signing.signing.Config().use_elliptic_key_verifier(
    public_key="key.pub"
)

for model in all_models:
    verifying_config.verify(model, f"{model}_sharded.sig")

The API defined here is stable and backwards compatible.

  1# Copyright 2024 The Sigstore Authors
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#      http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""High level API for the verification interface of `model_signing` library.
 16
 17This module supports configuring the verification method used to verify a model,
 18before performing the verification.
 19
 20```python
 21model_signing.verifying.Config().use_sigstore_verifier(
 22    identity=identity, oidc_issuer=oidc_provider
 23).verify("finbert", "finbert.sig")
 24```
 25
 26The same verification configuration can be used to verify multiple models:
 27
 28```python
 29verifying_config = model_signing.signing.Config().use_elliptic_key_verifier(
 30    public_key="key.pub"
 31)
 32
 33for model in all_models:
 34    verifying_config.verify(model, f"{model}_sharded.sig")
 35```
 36
 37The API defined here is stable and backwards compatible.
 38"""
 39
 40from collections.abc import Iterable
 41import pathlib
 42import sys
 43
 44from model_signing import hashing
 45from model_signing import manifest
 46from model_signing._signing import sign_certificate as certificate
 47from model_signing._signing import sign_ec_key as ec_key
 48from model_signing._signing import sign_sigstore as sigstore
 49from model_signing._signing import sign_sigstore_pb as sigstore_pb
 50
 51
 52if sys.version_info >= (3, 11):
 53    from typing import Self
 54else:
 55    from typing_extensions import Self
 56
 57
 58class Config:
 59    """Configuration to use when verifying models against signatures.
 60
 61    The verification configuration is needed to determine how to read and verify
 62    the signature. Given we support multiple signing format, the verification
 63    settings must match the signing ones.
 64
 65    The configuration also supports configuring the hashing configuration from
 66    `model_signing.hashing`. This should also match the configuration used
 67    during signing. However, by default, we can attempt to guess it from the
 68    signature.
 69    """
 70
 71    def __init__(self):
 72        """Initializes the default configuration for verification."""
 73        self._hashing_config = None
 74        self._verifier = None
 75        self._uses_sigstore = False
 76        self._ignore_unsigned_files = False
 77
 78    def verify(
 79        self, model_path: hashing.PathLike, signature_path: hashing.PathLike
 80    ):
 81        """Verifies that a model conforms to a signature.
 82
 83        Args:
 84            model_path: The path to the model to verify.
 85
 86        Raises:
 87            ValueError: No verifier has been configured.
 88        """
 89        if self._verifier is None:
 90            raise ValueError("Attempting to verify with no configured verifier")
 91
 92        if self._uses_sigstore:
 93            signature = sigstore.Signature.read(pathlib.Path(signature_path))
 94        else:
 95            signature = sigstore_pb.Signature.read(pathlib.Path(signature_path))
 96
 97        expected_manifest = self._verifier.verify(signature)
 98
 99        if self._hashing_config is None:
100            self._guess_hashing_config(expected_manifest)
101        if "ignore_paths" in expected_manifest.serialization_type:
102            self._hashing_config.add_ignored_paths(
103                model_path=model_path,
104                paths=expected_manifest.serialization_type["ignore_paths"],
105            )
106
107        if self._ignore_unsigned_files:
108            files_to_hash = [
109                model_path / rd.identifier
110                for rd in expected_manifest.resource_descriptors()
111            ]
112        else:
113            files_to_hash = None
114
115        actual_manifest = self._hashing_config.hash(
116            model_path, files_to_hash=files_to_hash
117        )
118
119        if actual_manifest != expected_manifest:
120            diff_message = self._get_manifest_diff(
121                actual_manifest, expected_manifest
122            )
123            raise ValueError(f"Signature mismatch: {diff_message}")
124
125    def _get_manifest_diff(self, actual, expected) -> list[str]:
126        diffs = []
127
128        actual_hashes = {
129            rd.identifier: rd.digest for rd in actual.resource_descriptors()
130        }
131        expected_hashes = {
132            rd.identifier: rd.digest for rd in expected.resource_descriptors()
133        }
134
135        extra_actual_files = set(actual_hashes.keys()) - set(
136            expected_hashes.keys()
137        )
138        if extra_actual_files:
139            diffs.append(
140                f"Extra files found in model '{actual.model_name}': "
141                f"{', '.join(sorted(extra_actual_files))}"
142            )
143
144        missing_actual_files = set(expected_hashes.keys()) - set(
145            actual_hashes.keys()
146        )
147        if missing_actual_files:
148            diffs.append(
149                f"Missing files in model '{actual.model_name}': "
150                f"{', '.join(sorted(missing_actual_files))}"
151            )
152
153        common_files = set(actual_hashes.keys()) & set(expected_hashes.keys())
154        for identifier in sorted(common_files):
155            if actual_hashes[identifier] != expected_hashes[identifier]:
156                diffs.append(
157                    f"Hash mismatch for '{identifier}': "
158                    f"Expected '{expected_hashes[identifier]}', "
159                    f"Actual '{actual_hashes[identifier]}'"
160                )
161        return diffs
162
163    def set_hashing_config(self, hashing_config: hashing.Config) -> Self:
164        """Sets the new configuration for hashing models.
165
166        After calling this method, the automatic guessing of the hashing
167        configuration used during signing is no longer possible from within one
168        instance of this class.
169
170        Args:
171            hashing_config: The new hashing configuration.
172
173        Returns:
174            The new signing configuration.
175        """
176        self._hashing_config = hashing_config
177        return self
178
179    def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self:
180        """Sets whether files that were not signed are to be ignored.
181
182        This method allows to ignore those files that are not part of the
183        manifest and therefor were not originally signed.
184
185        Args:
186            ignore_unsigned_files: whether to ignore unsigned files
187        """
188        self._ignore_unsigned_files = ignore_unsigned_files
189        return self
190
191    def _guess_hashing_config(self, source_manifest: manifest.Manifest) -> None:
192        """Attempts to guess the hashing config from a manifest."""
193        args = source_manifest.serialization_type
194        method = args["method"]
195        match method:
196            case "files":
197                self._hashing_config = hashing.Config().use_file_serialization(
198                    hashing_algorithm=args["hash_type"],
199                    allow_symlinks=args["allow_symlinks"],
200                    ignore_paths=args.get("ignore_paths", frozenset()),
201                )
202            case "shards":
203                self._hashing_config = hashing.Config().use_shard_serialization(
204                    hashing_algorithm=args["hash_type"],
205                    shard_size=args["shard_size"],
206                    allow_symlinks=args["allow_symlinks"],
207                    ignore_paths=args.get("ignore_paths", frozenset()),
208                )
209            case _:
210                raise ValueError("Cannot guess the hashing configuration")
211
212    def use_sigstore_verifier(
213        self,
214        *,
215        identity: str,
216        oidc_issuer: str,
217        use_staging: bool = False,
218        trust_config: pathlib.Path | None = None,
219    ) -> Self:
220        """Configures the verification of signatures produced by Sigstore.
221
222        The verifier in this configuration is changed to one that performs
223        verification of Sigstore signatures (sigstore bundles signed by
224        keyless signing via Sigstore).
225
226        Args:
227            identity: The expected identity that has signed the model.
228            oidc_issuer: The expected OpenID Connect issuer that provided the
229              certificate used for the signature.
230            use_staging: Use staging configurations, instead of production. This
231              is supposed to be set to True only when testing. Default is False.
232            trust_config: A path to a custom trust configuration. When provided,
233              the signature verification process will rely on the supplied
234              PKI and trust configurations, instead of the default Sigstore
235              setup. If not specified, the default Sigstore configuration
236              is used.
237
238        Return:
239            The new verification configuration.
240        """
241        self._uses_sigstore = True
242        self._verifier = sigstore.Verifier(
243            identity=identity,
244            oidc_issuer=oidc_issuer,
245            use_staging=use_staging,
246            trust_config=trust_config,
247        )
248        return self
249
250    def use_elliptic_key_verifier(
251        self, *, public_key: hashing.PathLike
252    ) -> Self:
253        """Configures the verification of signatures generated by a private key.
254
255        The verifier in this configuration is changed to one that performs
256        verification of sgistore bundles signed by an elliptic curve private
257        key. The public key used in the configuration must match the private key
258        used during signing.
259
260        Args:
261            public_key: The path to the public key to verify with.
262
263        Return:
264            The new verification configuration.
265        """
266        self._uses_sigstore = False
267        self._verifier = ec_key.Verifier(pathlib.Path(public_key))
268        return self
269
270    def use_certificate_verifier(
271        self,
272        *,
273        certificate_chain: Iterable[hashing.PathLike] = frozenset(),
274        log_fingerprints: bool = False,
275    ) -> Self:
276        """Configures the verification of signatures generated by a certificate.
277
278        The verifier in this configuration is changed to one that performs
279        verification of sgistore bundles signed by a signing certificate.
280
281        Args:
282            certificate_chain: Certificate chain to establish root of trust. If
283              empty, the operating system's one is used.
284            log_fingerprints: Log certificates' SHA256 fingerprints
285
286        Return:
287            The new verification configuration.
288        """
289        self._uses_sigstore = False
290        self._verifier = certificate.Verifier(
291            [pathlib.Path(c) for c in certificate_chain],
292            log_fingerprints=log_fingerprints,
293        )
294        return self
class Config:
 59class Config:
 60    """Configuration to use when verifying models against signatures.
 61
 62    The verification configuration is needed to determine how to read and verify
 63    the signature. Given we support multiple signing format, the verification
 64    settings must match the signing ones.
 65
 66    The configuration also supports configuring the hashing configuration from
 67    `model_signing.hashing`. This should also match the configuration used
 68    during signing. However, by default, we can attempt to guess it from the
 69    signature.
 70    """
 71
 72    def __init__(self):
 73        """Initializes the default configuration for verification."""
 74        self._hashing_config = None
 75        self._verifier = None
 76        self._uses_sigstore = False
 77        self._ignore_unsigned_files = False
 78
 79    def verify(
 80        self, model_path: hashing.PathLike, signature_path: hashing.PathLike
 81    ):
 82        """Verifies that a model conforms to a signature.
 83
 84        Args:
 85            model_path: The path to the model to verify.
 86
 87        Raises:
 88            ValueError: No verifier has been configured.
 89        """
 90        if self._verifier is None:
 91            raise ValueError("Attempting to verify with no configured verifier")
 92
 93        if self._uses_sigstore:
 94            signature = sigstore.Signature.read(pathlib.Path(signature_path))
 95        else:
 96            signature = sigstore_pb.Signature.read(pathlib.Path(signature_path))
 97
 98        expected_manifest = self._verifier.verify(signature)
 99
100        if self._hashing_config is None:
101            self._guess_hashing_config(expected_manifest)
102        if "ignore_paths" in expected_manifest.serialization_type:
103            self._hashing_config.add_ignored_paths(
104                model_path=model_path,
105                paths=expected_manifest.serialization_type["ignore_paths"],
106            )
107
108        if self._ignore_unsigned_files:
109            files_to_hash = [
110                model_path / rd.identifier
111                for rd in expected_manifest.resource_descriptors()
112            ]
113        else:
114            files_to_hash = None
115
116        actual_manifest = self._hashing_config.hash(
117            model_path, files_to_hash=files_to_hash
118        )
119
120        if actual_manifest != expected_manifest:
121            diff_message = self._get_manifest_diff(
122                actual_manifest, expected_manifest
123            )
124            raise ValueError(f"Signature mismatch: {diff_message}")
125
126    def _get_manifest_diff(self, actual, expected) -> list[str]:
127        diffs = []
128
129        actual_hashes = {
130            rd.identifier: rd.digest for rd in actual.resource_descriptors()
131        }
132        expected_hashes = {
133            rd.identifier: rd.digest for rd in expected.resource_descriptors()
134        }
135
136        extra_actual_files = set(actual_hashes.keys()) - set(
137            expected_hashes.keys()
138        )
139        if extra_actual_files:
140            diffs.append(
141                f"Extra files found in model '{actual.model_name}': "
142                f"{', '.join(sorted(extra_actual_files))}"
143            )
144
145        missing_actual_files = set(expected_hashes.keys()) - set(
146            actual_hashes.keys()
147        )
148        if missing_actual_files:
149            diffs.append(
150                f"Missing files in model '{actual.model_name}': "
151                f"{', '.join(sorted(missing_actual_files))}"
152            )
153
154        common_files = set(actual_hashes.keys()) & set(expected_hashes.keys())
155        for identifier in sorted(common_files):
156            if actual_hashes[identifier] != expected_hashes[identifier]:
157                diffs.append(
158                    f"Hash mismatch for '{identifier}': "
159                    f"Expected '{expected_hashes[identifier]}', "
160                    f"Actual '{actual_hashes[identifier]}'"
161                )
162        return diffs
163
164    def set_hashing_config(self, hashing_config: hashing.Config) -> Self:
165        """Sets the new configuration for hashing models.
166
167        After calling this method, the automatic guessing of the hashing
168        configuration used during signing is no longer possible from within one
169        instance of this class.
170
171        Args:
172            hashing_config: The new hashing configuration.
173
174        Returns:
175            The new signing configuration.
176        """
177        self._hashing_config = hashing_config
178        return self
179
180    def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self:
181        """Sets whether files that were not signed are to be ignored.
182
183        This method allows to ignore those files that are not part of the
184        manifest and therefor were not originally signed.
185
186        Args:
187            ignore_unsigned_files: whether to ignore unsigned files
188        """
189        self._ignore_unsigned_files = ignore_unsigned_files
190        return self
191
192    def _guess_hashing_config(self, source_manifest: manifest.Manifest) -> None:
193        """Attempts to guess the hashing config from a manifest."""
194        args = source_manifest.serialization_type
195        method = args["method"]
196        match method:
197            case "files":
198                self._hashing_config = hashing.Config().use_file_serialization(
199                    hashing_algorithm=args["hash_type"],
200                    allow_symlinks=args["allow_symlinks"],
201                    ignore_paths=args.get("ignore_paths", frozenset()),
202                )
203            case "shards":
204                self._hashing_config = hashing.Config().use_shard_serialization(
205                    hashing_algorithm=args["hash_type"],
206                    shard_size=args["shard_size"],
207                    allow_symlinks=args["allow_symlinks"],
208                    ignore_paths=args.get("ignore_paths", frozenset()),
209                )
210            case _:
211                raise ValueError("Cannot guess the hashing configuration")
212
213    def use_sigstore_verifier(
214        self,
215        *,
216        identity: str,
217        oidc_issuer: str,
218        use_staging: bool = False,
219        trust_config: pathlib.Path | None = None,
220    ) -> Self:
221        """Configures the verification of signatures produced by Sigstore.
222
223        The verifier in this configuration is changed to one that performs
224        verification of Sigstore signatures (sigstore bundles signed by
225        keyless signing via Sigstore).
226
227        Args:
228            identity: The expected identity that has signed the model.
229            oidc_issuer: The expected OpenID Connect issuer that provided the
230              certificate used for the signature.
231            use_staging: Use staging configurations, instead of production. This
232              is supposed to be set to True only when testing. Default is False.
233            trust_config: A path to a custom trust configuration. When provided,
234              the signature verification process will rely on the supplied
235              PKI and trust configurations, instead of the default Sigstore
236              setup. If not specified, the default Sigstore configuration
237              is used.
238
239        Return:
240            The new verification configuration.
241        """
242        self._uses_sigstore = True
243        self._verifier = sigstore.Verifier(
244            identity=identity,
245            oidc_issuer=oidc_issuer,
246            use_staging=use_staging,
247            trust_config=trust_config,
248        )
249        return self
250
251    def use_elliptic_key_verifier(
252        self, *, public_key: hashing.PathLike
253    ) -> Self:
254        """Configures the verification of signatures generated by a private key.
255
256        The verifier in this configuration is changed to one that performs
257        verification of sgistore bundles signed by an elliptic curve private
258        key. The public key used in the configuration must match the private key
259        used during signing.
260
261        Args:
262            public_key: The path to the public key to verify with.
263
264        Return:
265            The new verification configuration.
266        """
267        self._uses_sigstore = False
268        self._verifier = ec_key.Verifier(pathlib.Path(public_key))
269        return self
270
271    def use_certificate_verifier(
272        self,
273        *,
274        certificate_chain: Iterable[hashing.PathLike] = frozenset(),
275        log_fingerprints: bool = False,
276    ) -> Self:
277        """Configures the verification of signatures generated by a certificate.
278
279        The verifier in this configuration is changed to one that performs
280        verification of sgistore bundles signed by a signing certificate.
281
282        Args:
283            certificate_chain: Certificate chain to establish root of trust. If
284              empty, the operating system's one is used.
285            log_fingerprints: Log certificates' SHA256 fingerprints
286
287        Return:
288            The new verification configuration.
289        """
290        self._uses_sigstore = False
291        self._verifier = certificate.Verifier(
292            [pathlib.Path(c) for c in certificate_chain],
293            log_fingerprints=log_fingerprints,
294        )
295        return self

Configuration to use when verifying models against signatures.

The verification configuration is needed to determine how to read and verify the signature. Given we support multiple signing format, the verification settings must match the signing ones.

The configuration also supports configuring the hashing configuration from model_signing.hashing. This should also match the configuration used during signing. However, by default, we can attempt to guess it from the signature.

Config()
72    def __init__(self):
73        """Initializes the default configuration for verification."""
74        self._hashing_config = None
75        self._verifier = None
76        self._uses_sigstore = False
77        self._ignore_unsigned_files = False

Initializes the default configuration for verification.

def verify( self, model_path: str | bytes | os.PathLike, signature_path: str | bytes | os.PathLike):
 79    def verify(
 80        self, model_path: hashing.PathLike, signature_path: hashing.PathLike
 81    ):
 82        """Verifies that a model conforms to a signature.
 83
 84        Args:
 85            model_path: The path to the model to verify.
 86
 87        Raises:
 88            ValueError: No verifier has been configured.
 89        """
 90        if self._verifier is None:
 91            raise ValueError("Attempting to verify with no configured verifier")
 92
 93        if self._uses_sigstore:
 94            signature = sigstore.Signature.read(pathlib.Path(signature_path))
 95        else:
 96            signature = sigstore_pb.Signature.read(pathlib.Path(signature_path))
 97
 98        expected_manifest = self._verifier.verify(signature)
 99
100        if self._hashing_config is None:
101            self._guess_hashing_config(expected_manifest)
102        if "ignore_paths" in expected_manifest.serialization_type:
103            self._hashing_config.add_ignored_paths(
104                model_path=model_path,
105                paths=expected_manifest.serialization_type["ignore_paths"],
106            )
107
108        if self._ignore_unsigned_files:
109            files_to_hash = [
110                model_path / rd.identifier
111                for rd in expected_manifest.resource_descriptors()
112            ]
113        else:
114            files_to_hash = None
115
116        actual_manifest = self._hashing_config.hash(
117            model_path, files_to_hash=files_to_hash
118        )
119
120        if actual_manifest != expected_manifest:
121            diff_message = self._get_manifest_diff(
122                actual_manifest, expected_manifest
123            )
124            raise ValueError(f"Signature mismatch: {diff_message}")

Verifies that a model conforms to a signature.

Arguments:
  • model_path: The path to the model to verify.
Raises:
  • ValueError: No verifier has been configured.
def set_hashing_config(self, hashing_config: model_signing.hashing.Config) -> Self:
164    def set_hashing_config(self, hashing_config: hashing.Config) -> Self:
165        """Sets the new configuration for hashing models.
166
167        After calling this method, the automatic guessing of the hashing
168        configuration used during signing is no longer possible from within one
169        instance of this class.
170
171        Args:
172            hashing_config: The new hashing configuration.
173
174        Returns:
175            The new signing configuration.
176        """
177        self._hashing_config = hashing_config
178        return self

Sets the new configuration for hashing models.

After calling this method, the automatic guessing of the hashing configuration used during signing is no longer possible from within one instance of this class.

Arguments:
  • hashing_config: The new hashing configuration.
Returns:

The new signing configuration.

def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self:
180    def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self:
181        """Sets whether files that were not signed are to be ignored.
182
183        This method allows to ignore those files that are not part of the
184        manifest and therefor were not originally signed.
185
186        Args:
187            ignore_unsigned_files: whether to ignore unsigned files
188        """
189        self._ignore_unsigned_files = ignore_unsigned_files
190        return self

Sets whether files that were not signed are to be ignored.

This method allows to ignore those files that are not part of the manifest and therefor were not originally signed.

Arguments:
  • ignore_unsigned_files: whether to ignore unsigned files
def use_sigstore_verifier( self, *, identity: str, oidc_issuer: str, use_staging: bool = False, trust_config: pathlib.Path | None = None) -> Self:
213    def use_sigstore_verifier(
214        self,
215        *,
216        identity: str,
217        oidc_issuer: str,
218        use_staging: bool = False,
219        trust_config: pathlib.Path | None = None,
220    ) -> Self:
221        """Configures the verification of signatures produced by Sigstore.
222
223        The verifier in this configuration is changed to one that performs
224        verification of Sigstore signatures (sigstore bundles signed by
225        keyless signing via Sigstore).
226
227        Args:
228            identity: The expected identity that has signed the model.
229            oidc_issuer: The expected OpenID Connect issuer that provided the
230              certificate used for the signature.
231            use_staging: Use staging configurations, instead of production. This
232              is supposed to be set to True only when testing. Default is False.
233            trust_config: A path to a custom trust configuration. When provided,
234              the signature verification process will rely on the supplied
235              PKI and trust configurations, instead of the default Sigstore
236              setup. If not specified, the default Sigstore configuration
237              is used.
238
239        Return:
240            The new verification configuration.
241        """
242        self._uses_sigstore = True
243        self._verifier = sigstore.Verifier(
244            identity=identity,
245            oidc_issuer=oidc_issuer,
246            use_staging=use_staging,
247            trust_config=trust_config,
248        )
249        return self

Configures the verification of signatures produced by Sigstore.

The verifier in this configuration is changed to one that performs verification of Sigstore signatures (sigstore bundles signed by keyless signing via Sigstore).

Arguments:
  • identity: The expected identity that has signed the model.
  • oidc_issuer: The expected OpenID Connect issuer that provided the certificate used for the signature.
  • use_staging: Use staging configurations, instead of production. This is supposed to be set to True only when testing. Default is False.
  • trust_config: A path to a custom trust configuration. When provided, the signature verification process will rely on the supplied PKI and trust configurations, instead of the default Sigstore setup. If not specified, the default Sigstore configuration is used.
Return:

The new verification configuration.

def use_elliptic_key_verifier(self, *, public_key: str | bytes | os.PathLike) -> Self:
251    def use_elliptic_key_verifier(
252        self, *, public_key: hashing.PathLike
253    ) -> Self:
254        """Configures the verification of signatures generated by a private key.
255
256        The verifier in this configuration is changed to one that performs
257        verification of sgistore bundles signed by an elliptic curve private
258        key. The public key used in the configuration must match the private key
259        used during signing.
260
261        Args:
262            public_key: The path to the public key to verify with.
263
264        Return:
265            The new verification configuration.
266        """
267        self._uses_sigstore = False
268        self._verifier = ec_key.Verifier(pathlib.Path(public_key))
269        return self

Configures the verification of signatures generated by a private key.

The verifier in this configuration is changed to one that performs verification of sgistore bundles signed by an elliptic curve private key. The public key used in the configuration must match the private key used during signing.

Arguments:
  • public_key: The path to the public key to verify with.
Return:

The new verification configuration.

def use_certificate_verifier( self, *, certificate_chain: Iterable[str | bytes | os.PathLike] = frozenset(), log_fingerprints: bool = False) -> Self:
271    def use_certificate_verifier(
272        self,
273        *,
274        certificate_chain: Iterable[hashing.PathLike] = frozenset(),
275        log_fingerprints: bool = False,
276    ) -> Self:
277        """Configures the verification of signatures generated by a certificate.
278
279        The verifier in this configuration is changed to one that performs
280        verification of sgistore bundles signed by a signing certificate.
281
282        Args:
283            certificate_chain: Certificate chain to establish root of trust. If
284              empty, the operating system's one is used.
285            log_fingerprints: Log certificates' SHA256 fingerprints
286
287        Return:
288            The new verification configuration.
289        """
290        self._uses_sigstore = False
291        self._verifier = certificate.Verifier(
292            [pathlib.Path(c) for c in certificate_chain],
293            log_fingerprints=log_fingerprints,
294        )
295        return self

Configures the verification of signatures generated by a certificate.

The verifier in this configuration is changed to one that performs verification of sgistore bundles signed by a signing certificate.

Arguments:
  • certificate_chain: Certificate chain to establish root of trust. If empty, the operating system's one is used.
  • log_fingerprints: Log certificates' SHA256 fingerprints
Return:

The new verification configuration.