sigstore._internal.fulcio
APIs for interacting with Fulcio.
1# Copyright 2022 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""" 16APIs for interacting with Fulcio. 17""" 18 19from .client import ( 20 DetachedFulcioSCT, 21 ExpiredCertificate, 22 FulcioCertificateSigningResponse, 23 FulcioClient, 24) 25 26__all__ = [ 27 "DetachedFulcioSCT", 28 "ExpiredCertificate", 29 "FulcioCertificateSigningResponse", 30 "FulcioClient", 31]
99class DetachedFulcioSCT(BaseModel): 100 """ 101 Represents a "detached" SignedCertificateTimestamp from Fulcio. 102 """ 103 104 model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True) 105 106 version: Version = Field(..., alias="sct_version") 107 log_id: bytes = Field(..., alias="id") 108 timestamp: datetime.datetime 109 digitally_signed: bytes = Field(..., alias="signature") 110 extension_bytes: bytes = Field(..., alias="extensions") 111 112 @field_validator("timestamp") 113 def _validate_timestamp(cls, v: datetime.datetime) -> datetime.datetime: 114 return v.replace(tzinfo=datetime.timezone.utc) 115 116 @field_validator("digitally_signed", mode="before") 117 def _validate_digitally_signed(cls, v: bytes) -> bytes: 118 digitally_signed = base64.b64decode(v) 119 120 if len(digitally_signed) <= 4: 121 raise ValueError("impossibly small digitally-signed struct") 122 123 return digitally_signed 124 125 @field_validator("log_id", mode="before") 126 def _validate_log_id(cls, v: bytes) -> bytes: 127 return base64.b64decode(v) 128 129 @field_validator("extension_bytes", mode="before") 130 def _validate_extensions(cls, v: bytes) -> bytes: 131 return base64.b64decode(v) 132 133 @property 134 def entry_type(self) -> LogEntryType: 135 """ 136 Returns the kind of CT log entry this detached SCT is signing for. 137 """ 138 return LogEntryType.X509_CERTIFICATE 139 140 @property 141 def signature_hash_algorithm(self) -> hashes.HashAlgorithm: 142 """ 143 Returns the hash algorithm used in this detached SCT's signature. 144 """ 145 hash_ = SCTHashAlgorithm(self.digitally_signed[0]) 146 return hash_.to_cryptography() 147 148 @property 149 def signature_algorithm(self) -> SignatureAlgorithm: 150 """ 151 Returns the signature algorithm used in this detached SCT's signature. 152 """ 153 return SignatureAlgorithm(self.digitally_signed[1]) 154 155 @property 156 def signature(self) -> bytes: 157 """ 158 Returns the raw signature inside the detached SCT. 159 """ 160 (sig_size,) = struct.unpack("!H", self.digitally_signed[2:4]) 161 if len(self.digitally_signed[4:]) != sig_size: 162 raise FulcioSCTError( 163 f"signature size mismatch: expected {sig_size} bytes, " 164 f"got {len(self.digitally_signed[4:])}" 165 ) 166 return self.digitally_signed[4:]
Represents a "detached" SignedCertificateTimestamp from Fulcio.
Configuration for the model, should be a dictionary conforming to [ConfigDict
][pydantic.config.ConfigDict].
133 @property 134 def entry_type(self) -> LogEntryType: 135 """ 136 Returns the kind of CT log entry this detached SCT is signing for. 137 """ 138 return LogEntryType.X509_CERTIFICATE
Returns the kind of CT log entry this detached SCT is signing for.
140 @property 141 def signature_hash_algorithm(self) -> hashes.HashAlgorithm: 142 """ 143 Returns the hash algorithm used in this detached SCT's signature. 144 """ 145 hash_ = SCTHashAlgorithm(self.digitally_signed[0]) 146 return hash_.to_cryptography()
Returns the hash algorithm used in this detached SCT's signature.
148 @property 149 def signature_algorithm(self) -> SignatureAlgorithm: 150 """ 151 Returns the signature algorithm used in this detached SCT's signature. 152 """ 153 return SignatureAlgorithm(self.digitally_signed[1])
Returns the signature algorithm used in this detached SCT's signature.
155 @property 156 def signature(self) -> bytes: 157 """ 158 Returns the raw signature inside the detached SCT. 159 """ 160 (sig_size,) = struct.unpack("!H", self.digitally_signed[2:4]) 161 if len(self.digitally_signed[4:]) != sig_size: 162 raise FulcioSCTError( 163 f"signature size mismatch: expected {sig_size} bytes, " 164 f"got {len(self.digitally_signed[4:])}" 165 ) 166 return self.digitally_signed[4:]
Returns the raw signature inside the detached SCT.
Metadata about the fields defined on the model,
mapping of field names to [FieldInfo
][pydantic.fields.FieldInfo] objects.
This replaces Model.__fields__
from Pydantic V1.
An error raised when the Certificate is expired.
178@dataclass(frozen=True) 179class FulcioCertificateSigningResponse: 180 """Certificate response""" 181 182 cert: Certificate 183 chain: List[Certificate] 184 sct: SignedCertificateTimestamp
Certificate response
335class FulcioClient: 336 """The internal Fulcio client""" 337 338 def __init__(self, url: str = DEFAULT_FULCIO_URL) -> None: 339 """Initialize the client""" 340 _logger.debug(f"Fulcio client using URL: {url}") 341 self.url = url 342 self.session = requests.Session() 343 self.session.headers.update( 344 { 345 "User-Agent": USER_AGENT, 346 } 347 ) 348 349 def __del__(self) -> None: 350 """ 351 Destroys the underlying network session. 352 """ 353 self.session.close() 354 355 @classmethod 356 def production(cls) -> FulcioClient: 357 """ 358 Returns a `FulcioClient` for the Sigstore production instance of Fulcio. 359 """ 360 return cls(DEFAULT_FULCIO_URL) 361 362 @classmethod 363 def staging(cls) -> FulcioClient: 364 """ 365 Returns a `FulcioClient` for the Sigstore staging instance of Fulcio. 366 """ 367 return cls(STAGING_FULCIO_URL) 368 369 @property 370 def signing_cert(self) -> FulcioSigningCert: 371 """ 372 Returns a model capable of interacting with Fulcio's signing certificate endpoints. 373 """ 374 return FulcioSigningCert( 375 urljoin(self.url, SIGNING_CERT_ENDPOINT), session=self.session 376 ) 377 378 @property 379 def trust_bundle(self) -> FulcioTrustBundle: 380 """ 381 Returns a model capable of interacting with Fulcio's trust bundle endpoints. 382 """ 383 return FulcioTrustBundle( 384 urljoin(self.url, TRUST_BUNDLE_ENDPOINT), session=self.session 385 )
The internal Fulcio client
338 def __init__(self, url: str = DEFAULT_FULCIO_URL) -> None: 339 """Initialize the client""" 340 _logger.debug(f"Fulcio client using URL: {url}") 341 self.url = url 342 self.session = requests.Session() 343 self.session.headers.update( 344 { 345 "User-Agent": USER_AGENT, 346 } 347 )
Initialize the client
355 @classmethod 356 def production(cls) -> FulcioClient: 357 """ 358 Returns a `FulcioClient` for the Sigstore production instance of Fulcio. 359 """ 360 return cls(DEFAULT_FULCIO_URL)
Returns a FulcioClient
for the Sigstore production instance of Fulcio.
362 @classmethod 363 def staging(cls) -> FulcioClient: 364 """ 365 Returns a `FulcioClient` for the Sigstore staging instance of Fulcio. 366 """ 367 return cls(STAGING_FULCIO_URL)
Returns a FulcioClient
for the Sigstore staging instance of Fulcio.
369 @property 370 def signing_cert(self) -> FulcioSigningCert: 371 """ 372 Returns a model capable of interacting with Fulcio's signing certificate endpoints. 373 """ 374 return FulcioSigningCert( 375 urljoin(self.url, SIGNING_CERT_ENDPOINT), session=self.session 376 )
Returns a model capable of interacting with Fulcio's signing certificate endpoints.
378 @property 379 def trust_bundle(self) -> FulcioTrustBundle: 380 """ 381 Returns a model capable of interacting with Fulcio's trust bundle endpoints. 382 """ 383 return FulcioTrustBundle( 384 urljoin(self.url, TRUST_BUNDLE_ENDPOINT), session=self.session 385 )
Returns a model capable of interacting with Fulcio's trust bundle endpoints.