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 copy 42import pathlib 43import sys 44 45from model_signing import hashing 46from model_signing import manifest 47from model_signing._signing import sign_certificate as certificate 48from model_signing._signing import sign_ec_key as ec_key 49from model_signing._signing import sign_sigstore as sigstore 50from model_signing._signing import sign_sigstore_pb as sigstore_pb 51 52 53if sys.version_info >= (3, 11): 54 from typing import Self 55else: 56 from typing_extensions import Self 57 58 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 signature_path: The path to the signature file. 87 88 Raises: 89 ValueError: No verifier has been configured. 90 """ 91 if self._verifier is None: 92 raise ValueError("Attempting to verify with no configured verifier") 93 94 if self._uses_sigstore: 95 signature = sigstore.Signature.read(pathlib.Path(signature_path)) 96 else: 97 signature = sigstore_pb.Signature.read(pathlib.Path(signature_path)) 98 99 expected_manifest = self._verifier.verify(signature) 100 101 if self._hashing_config is not None: 102 # The signed manifest's ignore paths are applied below. Copy the 103 # config so they do not mutate the caller's config or accumulate 104 # into later verify() calls on a reused instance. 105 hashing_config = copy.deepcopy(self._hashing_config) 106 else: 107 hashing_config = self._guess_hashing_config(expected_manifest) 108 # OMS v1.0 6.1.1: "The verifier MUST apply the same allow_symlinks 109 # policy recorded in serialization.allow_symlinks". Every verify 110 # subcommand passes a hashing config built from its own 111 # --allow-symlinks flag, so without this the caller's flag silently 112 # replaced the signed policy and _guess_hashing_config, which does read 113 # it, never ran (issue #666). 114 recorded_allow_symlinks = expected_manifest.serialization_type.get( 115 "allow_symlinks" 116 ) 117 if recorded_allow_symlinks is not None: 118 hashing_config.set_allow_symlinks(recorded_allow_symlinks) 119 120 if "ignore_paths" in expected_manifest.serialization_type: 121 hashing_config.add_ignored_paths( 122 model_path=model_path, 123 paths=expected_manifest.serialization_type["ignore_paths"], 124 ) 125 126 if self._ignore_unsigned_files: 127 files_to_hash = [ 128 model_path / rd.identifier 129 for rd in expected_manifest.resource_descriptors() 130 ] 131 else: 132 files_to_hash = None 133 134 actual_manifest = hashing_config.hash( 135 model_path, files_to_hash=files_to_hash 136 ) 137 138 if actual_manifest != expected_manifest: 139 diff_message = self._get_manifest_diff( 140 actual_manifest, expected_manifest 141 ) 142 raise ValueError(f"Signature mismatch: {diff_message}") 143 144 def _get_manifest_diff(self, actual, expected) -> list[str]: 145 diffs = [] 146 147 actual_hashes = { 148 rd.identifier: rd.digest for rd in actual.resource_descriptors() 149 } 150 expected_hashes = { 151 rd.identifier: rd.digest for rd in expected.resource_descriptors() 152 } 153 154 extra_actual_files = set(actual_hashes.keys()) - set( 155 expected_hashes.keys() 156 ) 157 if extra_actual_files: 158 diffs.append( 159 f"Extra files found in model '{actual.model_name}': " 160 f"{', '.join(sorted(extra_actual_files))}" 161 ) 162 163 missing_actual_files = set(expected_hashes.keys()) - set( 164 actual_hashes.keys() 165 ) 166 if missing_actual_files: 167 diffs.append( 168 f"Missing files in model '{actual.model_name}': " 169 f"{', '.join(sorted(missing_actual_files))}" 170 ) 171 172 common_files = set(actual_hashes.keys()) & set(expected_hashes.keys()) 173 for identifier in sorted(common_files): 174 if actual_hashes[identifier] != expected_hashes[identifier]: 175 diffs.append( 176 f"Hash mismatch for '{identifier}': " 177 f"Expected '{expected_hashes[identifier]}', " 178 f"Actual '{actual_hashes[identifier]}'" 179 ) 180 return diffs 181 182 def set_hashing_config(self, hashing_config: hashing.Config) -> Self: 183 """Sets the new configuration for hashing models. 184 185 After calling this method, the automatic guessing of the hashing 186 configuration used during signing is no longer possible from within one 187 instance of this class. 188 189 Args: 190 hashing_config: The new hashing configuration. 191 192 Returns: 193 The new signing configuration. 194 """ 195 self._hashing_config = hashing_config 196 return self 197 198 def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self: 199 """Sets whether files that were not signed are to be ignored. 200 201 This method allows to ignore those files that are not part of the 202 manifest and therefor were not originally signed. 203 204 Args: 205 ignore_unsigned_files: whether to ignore unsigned files 206 """ 207 self._ignore_unsigned_files = ignore_unsigned_files 208 return self 209 210 def _guess_hashing_config( 211 self, source_manifest: manifest.Manifest 212 ) -> hashing.Config: 213 """Attempts to guess the hashing config from a manifest.""" 214 args = source_manifest.serialization_type 215 method = args["method"] 216 match method: 217 case "files": 218 return hashing.Config().use_file_serialization( 219 hashing_algorithm=args["hash_type"], 220 allow_symlinks=args["allow_symlinks"], 221 ignore_paths=args.get("ignore_paths", frozenset()), 222 ) 223 case "shards": 224 return hashing.Config().use_shard_serialization( 225 hashing_algorithm=args["hash_type"], 226 shard_size=args["shard_size"], 227 allow_symlinks=args["allow_symlinks"], 228 ignore_paths=args.get("ignore_paths", frozenset()), 229 ) 230 case _: 231 raise ValueError("Cannot guess the hashing configuration") 232 233 def use_sigstore_verifier( 234 self, 235 *, 236 identity: str, 237 oidc_issuer: str, 238 use_staging: bool = False, 239 trust_config: pathlib.Path | None = None, 240 ) -> Self: 241 """Configures the verification of signatures produced by Sigstore. 242 243 The verifier in this configuration is changed to one that performs 244 verification of Sigstore signatures (sigstore bundles signed by 245 keyless signing via Sigstore). 246 247 Args: 248 identity: The expected identity that has signed the model. 249 oidc_issuer: The expected OpenID Connect issuer that provided the 250 certificate used for the signature. 251 use_staging: Use staging configurations, instead of production. This 252 is supposed to be set to True only when testing. Default is False. 253 trust_config: A path to a custom trust configuration. When provided, 254 the signature verification process will rely on the supplied 255 PKI and trust configurations, instead of the default Sigstore 256 setup. If not specified, the default Sigstore configuration 257 is used. 258 259 Return: 260 The new verification configuration. 261 """ 262 self._uses_sigstore = True 263 self._verifier = sigstore.Verifier( 264 identity=identity, 265 oidc_issuer=oidc_issuer, 266 use_staging=use_staging, 267 trust_config=trust_config, 268 ) 269 return self 270 271 def use_elliptic_key_verifier( 272 self, *, public_key: hashing.PathLike 273 ) -> Self: 274 """Configures the verification of signatures generated by a private key. 275 276 The verifier in this configuration is changed to one that performs 277 verification of sigstore bundles signed by an elliptic curve private 278 key. The public key used in the configuration must match the private key 279 used during signing. 280 281 Args: 282 public_key: The path to the public key to verify with. 283 284 Return: 285 The new verification configuration. 286 """ 287 self._uses_sigstore = False 288 self._verifier = ec_key.Verifier(pathlib.Path(public_key)) 289 return self 290 291 def use_certificate_verifier( 292 self, 293 *, 294 certificate_chain: Iterable[hashing.PathLike] = frozenset(), 295 log_fingerprints: bool = False, 296 expected_san_uris: Iterable[str] = frozenset(), 297 ) -> Self: 298 """Configures the verification of signatures generated by a certificate. 299 300 The verifier in this configuration is changed to one that performs 301 verification of sigstore bundles signed by a signing certificate. 302 303 Args: 304 certificate_chain: Certificate chain to establish root of trust. If 305 empty, the operating system's one is used. 306 log_fingerprints: Log certificates' SHA256 fingerprints 307 expected_san_uris: Optional URIs that must appear in the leaf 308 certificate's SubjectAltName. Binds the signature to a specific 309 signer identity (e.g. a SPIFFE ID) in addition to 310 chain-of-trust. 311 312 Return: 313 The new verification configuration. 314 """ 315 self._uses_sigstore = False 316 self._verifier = certificate.Verifier( 317 [pathlib.Path(c) for c in certificate_chain], 318 log_fingerprints=log_fingerprints, 319 expected_san_uris=expected_san_uris, 320 ) 321 return self
60class Config: 61 """Configuration to use when verifying models against signatures. 62 63 The verification configuration is needed to determine how to read and verify 64 the signature. Given we support multiple signing format, the verification 65 settings must match the signing ones. 66 67 The configuration also supports configuring the hashing configuration from 68 `model_signing.hashing`. This should also match the configuration used 69 during signing. However, by default, we can attempt to guess it from the 70 signature. 71 """ 72 73 def __init__(self): 74 """Initializes the default configuration for verification.""" 75 self._hashing_config = None 76 self._verifier = None 77 self._uses_sigstore = False 78 self._ignore_unsigned_files = False 79 80 def verify( 81 self, model_path: hashing.PathLike, signature_path: hashing.PathLike 82 ): 83 """Verifies that a model conforms to a signature. 84 85 Args: 86 model_path: The path to the model to verify. 87 signature_path: The path to the signature file. 88 89 Raises: 90 ValueError: No verifier has been configured. 91 """ 92 if self._verifier is None: 93 raise ValueError("Attempting to verify with no configured verifier") 94 95 if self._uses_sigstore: 96 signature = sigstore.Signature.read(pathlib.Path(signature_path)) 97 else: 98 signature = sigstore_pb.Signature.read(pathlib.Path(signature_path)) 99 100 expected_manifest = self._verifier.verify(signature) 101 102 if self._hashing_config is not None: 103 # The signed manifest's ignore paths are applied below. Copy the 104 # config so they do not mutate the caller's config or accumulate 105 # into later verify() calls on a reused instance. 106 hashing_config = copy.deepcopy(self._hashing_config) 107 else: 108 hashing_config = self._guess_hashing_config(expected_manifest) 109 # OMS v1.0 6.1.1: "The verifier MUST apply the same allow_symlinks 110 # policy recorded in serialization.allow_symlinks". Every verify 111 # subcommand passes a hashing config built from its own 112 # --allow-symlinks flag, so without this the caller's flag silently 113 # replaced the signed policy and _guess_hashing_config, which does read 114 # it, never ran (issue #666). 115 recorded_allow_symlinks = expected_manifest.serialization_type.get( 116 "allow_symlinks" 117 ) 118 if recorded_allow_symlinks is not None: 119 hashing_config.set_allow_symlinks(recorded_allow_symlinks) 120 121 if "ignore_paths" in expected_manifest.serialization_type: 122 hashing_config.add_ignored_paths( 123 model_path=model_path, 124 paths=expected_manifest.serialization_type["ignore_paths"], 125 ) 126 127 if self._ignore_unsigned_files: 128 files_to_hash = [ 129 model_path / rd.identifier 130 for rd in expected_manifest.resource_descriptors() 131 ] 132 else: 133 files_to_hash = None 134 135 actual_manifest = hashing_config.hash( 136 model_path, files_to_hash=files_to_hash 137 ) 138 139 if actual_manifest != expected_manifest: 140 diff_message = self._get_manifest_diff( 141 actual_manifest, expected_manifest 142 ) 143 raise ValueError(f"Signature mismatch: {diff_message}") 144 145 def _get_manifest_diff(self, actual, expected) -> list[str]: 146 diffs = [] 147 148 actual_hashes = { 149 rd.identifier: rd.digest for rd in actual.resource_descriptors() 150 } 151 expected_hashes = { 152 rd.identifier: rd.digest for rd in expected.resource_descriptors() 153 } 154 155 extra_actual_files = set(actual_hashes.keys()) - set( 156 expected_hashes.keys() 157 ) 158 if extra_actual_files: 159 diffs.append( 160 f"Extra files found in model '{actual.model_name}': " 161 f"{', '.join(sorted(extra_actual_files))}" 162 ) 163 164 missing_actual_files = set(expected_hashes.keys()) - set( 165 actual_hashes.keys() 166 ) 167 if missing_actual_files: 168 diffs.append( 169 f"Missing files in model '{actual.model_name}': " 170 f"{', '.join(sorted(missing_actual_files))}" 171 ) 172 173 common_files = set(actual_hashes.keys()) & set(expected_hashes.keys()) 174 for identifier in sorted(common_files): 175 if actual_hashes[identifier] != expected_hashes[identifier]: 176 diffs.append( 177 f"Hash mismatch for '{identifier}': " 178 f"Expected '{expected_hashes[identifier]}', " 179 f"Actual '{actual_hashes[identifier]}'" 180 ) 181 return diffs 182 183 def set_hashing_config(self, hashing_config: hashing.Config) -> Self: 184 """Sets the new configuration for hashing models. 185 186 After calling this method, the automatic guessing of the hashing 187 configuration used during signing is no longer possible from within one 188 instance of this class. 189 190 Args: 191 hashing_config: The new hashing configuration. 192 193 Returns: 194 The new signing configuration. 195 """ 196 self._hashing_config = hashing_config 197 return self 198 199 def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self: 200 """Sets whether files that were not signed are to be ignored. 201 202 This method allows to ignore those files that are not part of the 203 manifest and therefor were not originally signed. 204 205 Args: 206 ignore_unsigned_files: whether to ignore unsigned files 207 """ 208 self._ignore_unsigned_files = ignore_unsigned_files 209 return self 210 211 def _guess_hashing_config( 212 self, source_manifest: manifest.Manifest 213 ) -> hashing.Config: 214 """Attempts to guess the hashing config from a manifest.""" 215 args = source_manifest.serialization_type 216 method = args["method"] 217 match method: 218 case "files": 219 return hashing.Config().use_file_serialization( 220 hashing_algorithm=args["hash_type"], 221 allow_symlinks=args["allow_symlinks"], 222 ignore_paths=args.get("ignore_paths", frozenset()), 223 ) 224 case "shards": 225 return hashing.Config().use_shard_serialization( 226 hashing_algorithm=args["hash_type"], 227 shard_size=args["shard_size"], 228 allow_symlinks=args["allow_symlinks"], 229 ignore_paths=args.get("ignore_paths", frozenset()), 230 ) 231 case _: 232 raise ValueError("Cannot guess the hashing configuration") 233 234 def use_sigstore_verifier( 235 self, 236 *, 237 identity: str, 238 oidc_issuer: str, 239 use_staging: bool = False, 240 trust_config: pathlib.Path | None = None, 241 ) -> Self: 242 """Configures the verification of signatures produced by Sigstore. 243 244 The verifier in this configuration is changed to one that performs 245 verification of Sigstore signatures (sigstore bundles signed by 246 keyless signing via Sigstore). 247 248 Args: 249 identity: The expected identity that has signed the model. 250 oidc_issuer: The expected OpenID Connect issuer that provided the 251 certificate used for the signature. 252 use_staging: Use staging configurations, instead of production. This 253 is supposed to be set to True only when testing. Default is False. 254 trust_config: A path to a custom trust configuration. When provided, 255 the signature verification process will rely on the supplied 256 PKI and trust configurations, instead of the default Sigstore 257 setup. If not specified, the default Sigstore configuration 258 is used. 259 260 Return: 261 The new verification configuration. 262 """ 263 self._uses_sigstore = True 264 self._verifier = sigstore.Verifier( 265 identity=identity, 266 oidc_issuer=oidc_issuer, 267 use_staging=use_staging, 268 trust_config=trust_config, 269 ) 270 return self 271 272 def use_elliptic_key_verifier( 273 self, *, public_key: hashing.PathLike 274 ) -> Self: 275 """Configures the verification of signatures generated by a private key. 276 277 The verifier in this configuration is changed to one that performs 278 verification of sigstore bundles signed by an elliptic curve private 279 key. The public key used in the configuration must match the private key 280 used during signing. 281 282 Args: 283 public_key: The path to the public key to verify with. 284 285 Return: 286 The new verification configuration. 287 """ 288 self._uses_sigstore = False 289 self._verifier = ec_key.Verifier(pathlib.Path(public_key)) 290 return self 291 292 def use_certificate_verifier( 293 self, 294 *, 295 certificate_chain: Iterable[hashing.PathLike] = frozenset(), 296 log_fingerprints: bool = False, 297 expected_san_uris: Iterable[str] = frozenset(), 298 ) -> Self: 299 """Configures the verification of signatures generated by a certificate. 300 301 The verifier in this configuration is changed to one that performs 302 verification of sigstore bundles signed by a signing certificate. 303 304 Args: 305 certificate_chain: Certificate chain to establish root of trust. If 306 empty, the operating system's one is used. 307 log_fingerprints: Log certificates' SHA256 fingerprints 308 expected_san_uris: Optional URIs that must appear in the leaf 309 certificate's SubjectAltName. Binds the signature to a specific 310 signer identity (e.g. a SPIFFE ID) in addition to 311 chain-of-trust. 312 313 Return: 314 The new verification configuration. 315 """ 316 self._uses_sigstore = False 317 self._verifier = certificate.Verifier( 318 [pathlib.Path(c) for c in certificate_chain], 319 log_fingerprints=log_fingerprints, 320 expected_san_uris=expected_san_uris, 321 ) 322 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.
73 def __init__(self): 74 """Initializes the default configuration for verification.""" 75 self._hashing_config = None 76 self._verifier = None 77 self._uses_sigstore = False 78 self._ignore_unsigned_files = False
Initializes the default configuration for verification.
80 def verify( 81 self, model_path: hashing.PathLike, signature_path: hashing.PathLike 82 ): 83 """Verifies that a model conforms to a signature. 84 85 Args: 86 model_path: The path to the model to verify. 87 signature_path: The path to the signature file. 88 89 Raises: 90 ValueError: No verifier has been configured. 91 """ 92 if self._verifier is None: 93 raise ValueError("Attempting to verify with no configured verifier") 94 95 if self._uses_sigstore: 96 signature = sigstore.Signature.read(pathlib.Path(signature_path)) 97 else: 98 signature = sigstore_pb.Signature.read(pathlib.Path(signature_path)) 99 100 expected_manifest = self._verifier.verify(signature) 101 102 if self._hashing_config is not None: 103 # The signed manifest's ignore paths are applied below. Copy the 104 # config so they do not mutate the caller's config or accumulate 105 # into later verify() calls on a reused instance. 106 hashing_config = copy.deepcopy(self._hashing_config) 107 else: 108 hashing_config = self._guess_hashing_config(expected_manifest) 109 # OMS v1.0 6.1.1: "The verifier MUST apply the same allow_symlinks 110 # policy recorded in serialization.allow_symlinks". Every verify 111 # subcommand passes a hashing config built from its own 112 # --allow-symlinks flag, so without this the caller's flag silently 113 # replaced the signed policy and _guess_hashing_config, which does read 114 # it, never ran (issue #666). 115 recorded_allow_symlinks = expected_manifest.serialization_type.get( 116 "allow_symlinks" 117 ) 118 if recorded_allow_symlinks is not None: 119 hashing_config.set_allow_symlinks(recorded_allow_symlinks) 120 121 if "ignore_paths" in expected_manifest.serialization_type: 122 hashing_config.add_ignored_paths( 123 model_path=model_path, 124 paths=expected_manifest.serialization_type["ignore_paths"], 125 ) 126 127 if self._ignore_unsigned_files: 128 files_to_hash = [ 129 model_path / rd.identifier 130 for rd in expected_manifest.resource_descriptors() 131 ] 132 else: 133 files_to_hash = None 134 135 actual_manifest = hashing_config.hash( 136 model_path, files_to_hash=files_to_hash 137 ) 138 139 if actual_manifest != expected_manifest: 140 diff_message = self._get_manifest_diff( 141 actual_manifest, expected_manifest 142 ) 143 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.
- signature_path: The path to the signature file.
Raises:
- ValueError: No verifier has been configured.
183 def set_hashing_config(self, hashing_config: hashing.Config) -> Self: 184 """Sets the new configuration for hashing models. 185 186 After calling this method, the automatic guessing of the hashing 187 configuration used during signing is no longer possible from within one 188 instance of this class. 189 190 Args: 191 hashing_config: The new hashing configuration. 192 193 Returns: 194 The new signing configuration. 195 """ 196 self._hashing_config = hashing_config 197 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.
199 def set_ignore_unsigned_files(self, ignore_unsigned_files: bool) -> Self: 200 """Sets whether files that were not signed are to be ignored. 201 202 This method allows to ignore those files that are not part of the 203 manifest and therefor were not originally signed. 204 205 Args: 206 ignore_unsigned_files: whether to ignore unsigned files 207 """ 208 self._ignore_unsigned_files = ignore_unsigned_files 209 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
234 def use_sigstore_verifier( 235 self, 236 *, 237 identity: str, 238 oidc_issuer: str, 239 use_staging: bool = False, 240 trust_config: pathlib.Path | None = None, 241 ) -> Self: 242 """Configures the verification of signatures produced by Sigstore. 243 244 The verifier in this configuration is changed to one that performs 245 verification of Sigstore signatures (sigstore bundles signed by 246 keyless signing via Sigstore). 247 248 Args: 249 identity: The expected identity that has signed the model. 250 oidc_issuer: The expected OpenID Connect issuer that provided the 251 certificate used for the signature. 252 use_staging: Use staging configurations, instead of production. This 253 is supposed to be set to True only when testing. Default is False. 254 trust_config: A path to a custom trust configuration. When provided, 255 the signature verification process will rely on the supplied 256 PKI and trust configurations, instead of the default Sigstore 257 setup. If not specified, the default Sigstore configuration 258 is used. 259 260 Return: 261 The new verification configuration. 262 """ 263 self._uses_sigstore = True 264 self._verifier = sigstore.Verifier( 265 identity=identity, 266 oidc_issuer=oidc_issuer, 267 use_staging=use_staging, 268 trust_config=trust_config, 269 ) 270 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.
272 def use_elliptic_key_verifier( 273 self, *, public_key: hashing.PathLike 274 ) -> Self: 275 """Configures the verification of signatures generated by a private key. 276 277 The verifier in this configuration is changed to one that performs 278 verification of sigstore bundles signed by an elliptic curve private 279 key. The public key used in the configuration must match the private key 280 used during signing. 281 282 Args: 283 public_key: The path to the public key to verify with. 284 285 Return: 286 The new verification configuration. 287 """ 288 self._uses_sigstore = False 289 self._verifier = ec_key.Verifier(pathlib.Path(public_key)) 290 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 sigstore 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.
292 def use_certificate_verifier( 293 self, 294 *, 295 certificate_chain: Iterable[hashing.PathLike] = frozenset(), 296 log_fingerprints: bool = False, 297 expected_san_uris: Iterable[str] = frozenset(), 298 ) -> Self: 299 """Configures the verification of signatures generated by a certificate. 300 301 The verifier in this configuration is changed to one that performs 302 verification of sigstore bundles signed by a signing certificate. 303 304 Args: 305 certificate_chain: Certificate chain to establish root of trust. If 306 empty, the operating system's one is used. 307 log_fingerprints: Log certificates' SHA256 fingerprints 308 expected_san_uris: Optional URIs that must appear in the leaf 309 certificate's SubjectAltName. Binds the signature to a specific 310 signer identity (e.g. a SPIFFE ID) in addition to 311 chain-of-trust. 312 313 Return: 314 The new verification configuration. 315 """ 316 self._uses_sigstore = False 317 self._verifier = certificate.Verifier( 318 [pathlib.Path(c) for c in certificate_chain], 319 log_fingerprints=log_fingerprints, 320 expected_san_uris=expected_san_uris, 321 ) 322 return self
Configures the verification of signatures generated by a certificate.
The verifier in this configuration is changed to one that performs verification of sigstore 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
- expected_san_uris: Optional URIs that must appear in the leaf certificate's SubjectAltName. Binds the signature to a specific signer identity (e.g. a SPIFFE ID) in addition to chain-of-trust.
Return:
The new verification configuration.