dcap-qvl 0.3.0__cp37-abi3-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dcap-qvl might be problematic. Click here for more details.

dcap_qvl/__init__.py ADDED
@@ -0,0 +1,204 @@
1
+ """
2
+ DCAP Quote Verification Library
3
+
4
+ This package provides Python bindings for the DCAP (Data Center Attestation Primitives)
5
+ quote verification library implemented in Rust.
6
+
7
+ Main classes:
8
+ - QuoteCollateralV3: Represents quote collateral data
9
+ - VerifiedReport: Contains verification results
10
+
11
+ Main functions:
12
+ - verify: Verify a quote with collateral data
13
+ - get_collateral: Get collateral from PCCS URL
14
+ - get_collateral_from_pcs: Get collateral from Intel PCS
15
+ - get_collateral_and_verify: Get collateral and verify quote
16
+ """
17
+
18
+ import time
19
+ import json
20
+ from typing import Optional, Union
21
+
22
+ try:
23
+ import requests
24
+ except ImportError:
25
+ requests = None
26
+
27
+ from .dcap_qvl import (
28
+ PyQuoteCollateralV3 as QuoteCollateralV3,
29
+ PyVerifiedReport as VerifiedReport,
30
+ PyQuote as Quote,
31
+ py_verify as verify,
32
+ parse_quote,
33
+ )
34
+
35
+ # Default Intel PCS URL
36
+ PCS_URL = "https://api.trustedservices.intel.com"
37
+
38
+
39
+ # Note: These functions are now implemented in Rust and imported above
40
+ # The manual parsing logic has been replaced with proper Rust-based parsing
41
+
42
+
43
+ def _make_pcs_request(url: str) -> bytes:
44
+ """Make HTTP request to PCS endpoint."""
45
+ if requests is None:
46
+ raise ImportError(
47
+ "requests library is required for collateral fetching. Install with: pip install requests")
48
+
49
+ try:
50
+ response = requests.get(url, timeout=30, verify=False)
51
+ response.raise_for_status()
52
+ return response.content
53
+ except requests.RequestException as e:
54
+ raise RuntimeError(f"Failed to fetch from {url}: {e}")
55
+
56
+
57
+ def get_collateral(pccs_url: str, raw_quote: bytes) -> QuoteCollateralV3:
58
+ """Get collateral from PCCS URL.
59
+
60
+ Args:
61
+ pccs_url: PCCS server URL
62
+ raw_quote: Raw quote bytes
63
+
64
+ Returns:
65
+ QuoteCollateralV3: Quote collateral data
66
+
67
+ Raises:
68
+ ValueError: If quote is invalid or FMSPC cannot be extracted
69
+ RuntimeError: If network request fails
70
+ ImportError: If requests library is not available
71
+ """
72
+ if not isinstance(raw_quote, (bytes, bytearray)):
73
+ raise TypeError("raw_quote must be bytes")
74
+
75
+ quote = Quote.parse(raw_quote)
76
+ # Extract FMSPC from quote
77
+ fmspc = quote.fmspc()
78
+
79
+ # Determine if SGX or TDX
80
+ is_tdx = quote.is_tdx()
81
+ ca = quote.ca()
82
+
83
+ # Build PCS endpoints
84
+ base_url = pccs_url.rstrip('/')
85
+
86
+ if is_tdx:
87
+ # TDX endpoints
88
+ pckcrl_url = f"{base_url}/tdx/certification/v4/pckcrl?ca={ca}&encoding=der"
89
+ rootcacrl_url = f"{base_url}/tdx/certification/v4/rootcacrl"
90
+ tcb_url = f"{base_url}/tdx/certification/v4/tcb?fmspc={fmspc}"
91
+ qe_identity_url = f"{base_url}/tdx/certification/v4/qe/identity?update=standard"
92
+ else:
93
+ # SGX endpoints
94
+ pckcrl_url = f"{base_url}/sgx/certification/v4/pckcrl?ca={ca}&encoding=der"
95
+ rootcacrl_url = f"{base_url}/sgx/certification/v4/rootcacrl"
96
+ tcb_url = f"{base_url}/sgx/certification/v4/tcb?fmspc={fmspc}"
97
+ qe_identity_url = f"{base_url}/sgx/certification/v4/qe/identity?update=standard"
98
+
99
+ # Fetch collateral data
100
+ try:
101
+ # Get PCK CRL and issuer chain
102
+ pckcrl_response = _make_pcs_request(pckcrl_url)
103
+ pck_crl = pckcrl_response
104
+ pck_crl_issuer_chain = "" # Would need to parse from response headers
105
+
106
+ # Get Root CA CRL
107
+ root_ca_crl = _make_pcs_request(rootcacrl_url)
108
+
109
+ # Get TCB Info
110
+ tcb_response = _make_pcs_request(tcb_url)
111
+ tcb_data = json.loads(tcb_response.decode('utf-8'))
112
+ tcb_info = json.dumps(tcb_data.get('tcbInfo', {}))
113
+ tcb_info_issuer_chain = "" # Would need to parse from response headers
114
+
115
+ # Extract TCB signature
116
+ tcb_signature_hex = tcb_data.get('signature', '')
117
+ tcb_info_signature = bytes.fromhex(
118
+ tcb_signature_hex) if tcb_signature_hex else b''
119
+
120
+ # Get QE Identity
121
+ qe_response = _make_pcs_request(qe_identity_url)
122
+ qe_data = json.loads(qe_response.decode('utf-8'))
123
+ qe_identity = json.dumps(qe_data.get('enclaveIdentity', {}))
124
+ qe_identity_issuer_chain = "" # Would need to parse from response headers
125
+
126
+ # Extract QE signature
127
+ qe_signature_hex = qe_data.get('signature', '')
128
+ qe_identity_signature = bytes.fromhex(
129
+ qe_signature_hex) if qe_signature_hex else b''
130
+
131
+ return QuoteCollateralV3(
132
+ pck_crl_issuer_chain=pck_crl_issuer_chain,
133
+ root_ca_crl=root_ca_crl,
134
+ pck_crl=pck_crl,
135
+ tcb_info_issuer_chain=tcb_info_issuer_chain,
136
+ tcb_info=tcb_info,
137
+ tcb_info_signature=tcb_info_signature,
138
+ qe_identity_issuer_chain=qe_identity_issuer_chain,
139
+ qe_identity=qe_identity,
140
+ qe_identity_signature=qe_identity_signature,
141
+ )
142
+
143
+ except Exception as e:
144
+ raise RuntimeError(f"Failed to get collateral: {e}")
145
+
146
+
147
+ def get_collateral_from_pcs(raw_quote: bytes) -> QuoteCollateralV3:
148
+ """Get collateral from Intel PCS.
149
+
150
+ Args:
151
+ raw_quote: Raw quote bytes
152
+
153
+ Returns:
154
+ QuoteCollateralV3: Quote collateral data
155
+
156
+ Raises:
157
+ ValueError: If quote is invalid or FMSPC cannot be extracted
158
+ RuntimeError: If network request fails
159
+ ImportError: If requests library is not available
160
+ """
161
+ return get_collateral(PCS_URL, raw_quote)
162
+
163
+
164
+ def get_collateral_and_verify(raw_quote: bytes, pccs_url: Optional[str] = None) -> VerifiedReport:
165
+ """Get collateral and verify the quote.
166
+
167
+ Args:
168
+ raw_quote: Raw quote bytes
169
+ pccs_url: Optional PCCS URL (defaults to Intel PCS)
170
+
171
+ Returns:
172
+ VerifiedReport: Verification result
173
+
174
+ Raises:
175
+ ValueError: If quote is invalid or verification fails
176
+ RuntimeError: If network request fails
177
+ ImportError: If requests library is not available
178
+ """
179
+ # Use provided PCCS URL or default to Intel PCS
180
+ url = pccs_url.strip() if pccs_url else PCS_URL
181
+ if not url:
182
+ url = PCS_URL
183
+
184
+ # Get collateral
185
+ collateral = get_collateral(url, raw_quote)
186
+
187
+ # Get current time
188
+ now_secs = int(time.time())
189
+
190
+ # Verify quote
191
+ return verify(raw_quote, collateral, now_secs)
192
+
193
+
194
+ __all__ = [
195
+ "QuoteCollateralV3",
196
+ "VerifiedReport",
197
+ "Quote",
198
+ "verify",
199
+ "get_collateral",
200
+ "get_collateral_from_pcs",
201
+ "get_collateral_and_verify",
202
+ ]
203
+
204
+ __version__ = "0.3.0"
dcap_qvl/__init__.pyi ADDED
@@ -0,0 +1,334 @@
1
+ """
2
+ Type stubs for dcap_qvl Python bindings.
3
+
4
+ This file provides type hints for the compiled Rust extension, enabling better
5
+ IDE support, type checking with mypy, and improved developer experience.
6
+ """
7
+
8
+ from typing import List
9
+
10
+ __version__: str
11
+ __all__: List[str]
12
+
13
+
14
+ class QuoteCollateralV3:
15
+ """
16
+ Represents quote collateral data required for DCAP quote verification.
17
+
18
+ This class contains all the necessary certificate chains, CRLs, and
19
+ attestation information needed to verify an SGX or TDX quote.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ pck_crl_issuer_chain: str,
25
+ root_ca_crl: bytes,
26
+ pck_crl: bytes,
27
+ tcb_info_issuer_chain: str,
28
+ tcb_info: str,
29
+ tcb_info_signature: bytes,
30
+ qe_identity_issuer_chain: str,
31
+ qe_identity: str,
32
+ qe_identity_signature: bytes,
33
+ ) -> None:
34
+ """
35
+ Create a new QuoteCollateralV3 instance.
36
+
37
+ Args:
38
+ pck_crl_issuer_chain: PCK CRL issuer certificate chain (PEM format)
39
+ root_ca_crl: Root CA certificate revocation list
40
+ pck_crl: PCK certificate revocation list
41
+ tcb_info_issuer_chain: TCB info issuer certificate chain (PEM format)
42
+ tcb_info: TCB (Trusted Computing Base) information (JSON string)
43
+ tcb_info_signature: Signature for the TCB info
44
+ qe_identity_issuer_chain: QE identity issuer certificate chain (PEM format)
45
+ qe_identity: Quoting Enclave identity information (JSON string)
46
+ qe_identity_signature: Signature for the QE identity
47
+ """
48
+ ...
49
+
50
+ @property
51
+ def pck_crl_issuer_chain(self) -> str:
52
+ """PCK CRL issuer certificate chain in PEM format."""
53
+ ...
54
+
55
+ @property
56
+ def root_ca_crl(self) -> bytes:
57
+ """Root CA certificate revocation list."""
58
+ ...
59
+
60
+ @property
61
+ def pck_crl(self) -> bytes:
62
+ """PCK certificate revocation list."""
63
+ ...
64
+
65
+ @property
66
+ def tcb_info_issuer_chain(self) -> str:
67
+ """TCB info issuer certificate chain in PEM format."""
68
+ ...
69
+
70
+ @property
71
+ def tcb_info(self) -> str:
72
+ """TCB (Trusted Computing Base) information as JSON string."""
73
+ ...
74
+
75
+ @property
76
+ def tcb_info_signature(self) -> bytes:
77
+ """Signature for the TCB info."""
78
+ ...
79
+
80
+ @property
81
+ def qe_identity_issuer_chain(self) -> str:
82
+ """QE identity issuer certificate chain in PEM format."""
83
+ ...
84
+
85
+ @property
86
+ def qe_identity(self) -> str:
87
+ """Quoting Enclave identity information as JSON string."""
88
+ ...
89
+
90
+ @property
91
+ def qe_identity_signature(self) -> bytes:
92
+ """Signature for the QE identity."""
93
+ ...
94
+
95
+ def to_json(self) -> str:
96
+ """
97
+ Serialize the collateral to a JSON string.
98
+
99
+ Returns:
100
+ JSON string representation of the collateral data
101
+
102
+ Raises:
103
+ ValueError: If serialization fails
104
+ """
105
+ ...
106
+
107
+ @staticmethod
108
+ def from_json(json_str: str) -> "QuoteCollateralV3":
109
+ """
110
+ Create a QuoteCollateralV3 instance from a JSON string.
111
+
112
+ Args:
113
+ json_str: JSON string containing collateral data
114
+
115
+ Returns:
116
+ New QuoteCollateralV3 instance
117
+
118
+ Raises:
119
+ ValueError: If JSON parsing fails or data is invalid
120
+ """
121
+ ...
122
+
123
+
124
+ class VerifiedReport:
125
+ """
126
+ Contains the results of DCAP quote verification.
127
+
128
+ This class holds the verification status and any security advisories
129
+ that were found during the quote verification process.
130
+ """
131
+
132
+ @property
133
+ def status(self) -> str:
134
+ """
135
+ Verification status string.
136
+
137
+ Common values include:
138
+ - "OK": Verification successful, no issues
139
+ - "SW_HARDENING_NEEDED": Software hardening recommended
140
+ - "CONFIGURATION_NEEDED": Platform configuration required
141
+ - "OUT_OF_DATE": TCB is out of date
142
+ - "REVOKED": Certificate or key has been revoked
143
+ """
144
+ ...
145
+
146
+ @property
147
+ def advisory_ids(self) -> List[str]:
148
+ """
149
+ List of security advisory IDs that apply to this quote.
150
+
151
+ These are Intel security advisory identifiers (e.g., "INTEL-SA-00334")
152
+ that indicate known security issues affecting the attested platform.
153
+ """
154
+ ...
155
+
156
+ def to_json(self) -> str:
157
+ """
158
+ Serialize the verification report to a JSON string.
159
+
160
+ Returns:
161
+ JSON string representation of the verification report
162
+
163
+ Raises:
164
+ ValueError: If serialization fails
165
+ """
166
+ ...
167
+
168
+
169
+ class Quote:
170
+ """
171
+ Represents a parsed SGX or TDX quote.
172
+
173
+ This class provides access to quote metadata and identifiers
174
+ without requiring collateral data for verification.
175
+ """
176
+
177
+ @staticmethod
178
+ def parse(raw_quote: bytes) -> "Quote":
179
+ """
180
+ Parse a raw quote from bytes.
181
+
182
+ Args:
183
+ raw_quote: Raw quote data as bytes (SGX or TDX format)
184
+
185
+ Returns:
186
+ Quote instance with parsed quote data
187
+
188
+ Raises:
189
+ ValueError: If quote parsing fails due to invalid format or corrupted data
190
+
191
+ Example:
192
+ >>> import dcap_qvl
193
+ >>>
194
+ >>> with open("quote.bin", "rb") as f:
195
+ ... quote_data = f.read()
196
+ >>>
197
+ >>> quote = dcap_qvl.Quote.parse(quote_data)
198
+ >>> print(f"Quote type: {quote.quote_type()}")
199
+ >>> print(f"FMSPC: {quote.fmspc()}")
200
+ """
201
+ ...
202
+
203
+ def fmspc(self) -> str:
204
+ """
205
+ Extract the FMSPC (Family-Model-Stepping-Platform-CustomSKU) identifier.
206
+
207
+ The FMSPC is a 6-byte identifier that uniquely identifies the
208
+ platform's TCB level and is used for collateral retrieval.
209
+
210
+ Returns:
211
+ FMSPC as uppercase hexadecimal string (12 characters)
212
+
213
+ Raises:
214
+ ValueError: If FMSPC cannot be extracted from the quote
215
+
216
+ Example:
217
+ >>> quote = dcap_qvl.Quote.parse(quote_data)
218
+ >>> fmspc = quote.fmspc()
219
+ >>> print(f"FMSPC: {fmspc}") # e.g., "00606A000000"
220
+ """
221
+ ...
222
+
223
+ def ca(self) -> str:
224
+ """
225
+ Extract the CA (Certificate Authority) identifier.
226
+
227
+ The CA identifier indicates which certificate authority
228
+ should be used for quote verification.
229
+
230
+ Returns:
231
+ CA identifier as string
232
+
233
+ Raises:
234
+ ValueError: If CA identifier cannot be extracted from the quote
235
+ """
236
+ ...
237
+
238
+ def is_tdx(self) -> bool:
239
+ """
240
+ Check if this is a TDX (Trust Domain Extensions) quote.
241
+
242
+ Returns:
243
+ True if the quote is TDX format, False if SGX format
244
+
245
+ Example:
246
+ >>> quote = dcap_qvl.Quote.parse(quote_data)
247
+ >>> if quote.is_tdx():
248
+ ... print("This is a TDX quote")
249
+ ... else:
250
+ ... print("This is an SGX quote")
251
+ """
252
+ ...
253
+
254
+ def quote_type(self) -> str:
255
+ """
256
+ Get the quote type as a string.
257
+
258
+ Returns:
259
+ "TDX" for TDX quotes, "SGX" for SGX quotes
260
+
261
+ Example:
262
+ >>> quote = dcap_qvl.Quote.parse(quote_data)
263
+ >>> print(f"Quote type: {quote.quote_type()}")
264
+ """
265
+ ...
266
+
267
+ # Synchronous functions
268
+
269
+
270
+ def verify(
271
+ raw_quote: bytes,
272
+ collateral: QuoteCollateralV3,
273
+ now_secs: int
274
+ ) -> VerifiedReport:
275
+ """
276
+ Verify an SGX or TDX quote with the provided collateral data.
277
+
278
+ This function performs cryptographic verification of the quote against
279
+ the provided collateral information, checking certificates, signatures,
280
+ and revocation status.
281
+
282
+ Args:
283
+ raw_quote: Raw quote data as bytes (SGX or TDX format)
284
+ collateral: Quote collateral containing certificates and attestation data
285
+ now_secs: Current timestamp in seconds since Unix epoch for time-based checks
286
+
287
+ Returns:
288
+ VerifiedReport containing verification status and advisory information
289
+
290
+ Raises:
291
+ ValueError: If verification fails due to invalid data, expired certificates,
292
+ revoked keys, or other verification errors
293
+
294
+ Example:
295
+ >>> import dcap_qvl
296
+ >>> import time
297
+ >>>
298
+ >>> # Load quote and collateral data
299
+ >>> with open("quote.bin", "rb") as f:
300
+ ... quote_data = f.read()
301
+ >>>
302
+ >>> collateral = dcap_qvl.QuoteCollateralV3.from_json(collateral_json)
303
+ >>> result = dcap_qvl.verify(quote_data, collateral, int(time.time()))
304
+ >>> print(f"Status: {result.status}")
305
+ """
306
+ ...
307
+
308
+
309
+ def parse_quote(raw_quote: bytes) -> Quote:
310
+ """
311
+ Parse a raw quote from bytes (convenience function).
312
+
313
+ This is a convenience function that calls Quote.parse() directly.
314
+
315
+ Args:
316
+ raw_quote: Raw quote data as bytes (SGX or TDX format)
317
+
318
+ Returns:
319
+ Quote instance with parsed quote data
320
+
321
+ Raises:
322
+ ValueError: If quote parsing fails due to invalid format or corrupted data
323
+
324
+ Example:
325
+ >>> import dcap_qvl
326
+ >>>
327
+ >>> with open("quote.bin", "rb") as f:
328
+ ... quote_data = f.read()
329
+ >>>
330
+ >>> quote = dcap_qvl.parse_quote(quote_data)
331
+ >>> print(f"Quote type: {quote.quote_type()}")
332
+ >>> print(f"FMSPC: {quote.fmspc()}")
333
+ """
334
+ ...
Binary file
@@ -0,0 +1,335 @@
1
+ Metadata-Version: 2.4
2
+ Name: dcap-qvl
3
+ Version: 0.3.0
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.8
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Rust
14
+ Classifier: Topic :: Security :: Cryptography
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Summary: Python bindings for DCAP (Data Center Attestation Primitives) quote verification library
17
+ Keywords: sgx,tdx,dcap,attestation,verification,cryptography
18
+ Author-email: Kevin Wang <wy721@qq.com>
19
+ License: MIT
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
22
+ Project-URL: Homepage, https://github.com/Phala-Network/dcap-qvl
23
+ Project-URL: Repository, https://github.com/Phala-Network/dcap-qvl
24
+ Project-URL: Issues, https://github.com/Phala-Network/dcap-qvl/issues
25
+
26
+ # Python Bindings for DCAP-QVL
27
+
28
+ This package provides Python bindings for the DCAP (Data Center Attestation Primitives) quote verification library implemented in Rust.
29
+
30
+ ## Quick Start
31
+
32
+ ```bash
33
+ # Install from PyPI
34
+ pip install dcap-qvl
35
+
36
+ # Basic usage
37
+ python -c "
38
+ import dcap_qvl
39
+ print('DCAP-QVL Python bindings successfully installed!')
40
+ print(f'Available functions: {dcap_qvl.__all__}')
41
+ "
42
+ ```
43
+
44
+ ## Features
45
+
46
+ - Verify SGX and TDX quotes
47
+ - Handle quote collateral data
48
+ - Parse verification results
49
+ - Pure Rust implementation with Python bindings
50
+ - Cross-platform compatibility (Linux, macOS, Windows)
51
+ - Synchronous collateral fetching from PCCS/PCS
52
+ - Compatible with Python 3.8+
53
+
54
+ ## Installation
55
+
56
+ ### From PyPI (recommended)
57
+
58
+ ```bash
59
+ pip install dcap-qvl
60
+ ```
61
+
62
+ ### Using uv
63
+
64
+ ```bash
65
+ uv add dcap-qvl
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ ### Basic Quote Verification
71
+
72
+ ```python
73
+ import dcap_qvl
74
+ import json
75
+ import time
76
+
77
+ # Load quote data (binary)
78
+ with open("path/to/quote", "rb") as f:
79
+ quote_data = f.read()
80
+
81
+ # Load collateral data (JSON)
82
+ with open("path/to/collateral.json", "r") as f:
83
+ collateral_json = json.load(f)
84
+
85
+ # Create collateral object
86
+ collateral = dcap_qvl.QuoteCollateralV3.from_json(json.dumps(collateral_json))
87
+
88
+ # Verify the quote
89
+ now = int(time.time())
90
+ try:
91
+ result = dcap_qvl.verify(quote_data, collateral, now)
92
+ print(f"Verification successful! Status: {result.status}")
93
+ print(f"Advisory IDs: {result.advisory_ids}")
94
+ except ValueError as e:
95
+ print(f"Verification failed: {e}")
96
+ ```
97
+
98
+ ### Working with Collateral Data
99
+
100
+ ```python
101
+ # Create collateral manually
102
+ collateral = dcap_qvl.QuoteCollateralV3(
103
+ pck_crl_issuer_chain="...",
104
+ root_ca_crl=b"...", # bytes
105
+ pck_crl=b"...", # bytes
106
+ tcb_info_issuer_chain="...",
107
+ tcb_info="...", # JSON string
108
+ tcb_info_signature=b"...", # bytes
109
+ qe_identity_issuer_chain="...",
110
+ qe_identity="...", # JSON string
111
+ qe_identity_signature=b"...", # bytes
112
+ )
113
+
114
+ # Serialize to JSON
115
+ json_str = collateral.to_json()
116
+
117
+ # Deserialize from JSON
118
+ collateral = dcap_qvl.QuoteCollateralV3.from_json(json_str)
119
+ ```
120
+
121
+ ## API Reference
122
+
123
+ ### Collateral Functions
124
+
125
+ #### `get_collateral(pccs_url: str, raw_quote: bytes) -> QuoteCollateralV3`
126
+
127
+ Get collateral from a custom PCCS URL.
128
+
129
+ **Parameters:**
130
+ - `pccs_url`: PCCS URL (e.g., "https://api.trustedservices.intel.com")
131
+ - `raw_quote`: Raw quote data as bytes
132
+
133
+ **Returns:**
134
+ - `QuoteCollateralV3`: Quote collateral data
135
+
136
+ **Raises:**
137
+ - `ValueError`: If quote is invalid or FMSPC cannot be extracted
138
+ - `RuntimeError`: If network request fails
139
+ - `ImportError`: If requests library is not available
140
+
141
+ **Example:**
142
+ ```python
143
+ import dcap_qvl
144
+
145
+ pccs_url = "https://api.trustedservices.intel.com"
146
+ quote_data = open("quote.bin", "rb").read()
147
+ collateral = dcap_qvl.get_collateral(pccs_url, quote_data)
148
+ print(f"Got collateral: {len(collateral.tcb_info)} chars")
149
+ ```
150
+
151
+ #### `get_collateral_from_pcs(raw_quote: bytes) -> QuoteCollateralV3`
152
+
153
+ Get collateral from Intel's PCS (default).
154
+
155
+ **Parameters:**
156
+ - `raw_quote`: Raw quote data as bytes
157
+
158
+ **Returns:**
159
+ - `QuoteCollateralV3`: Quote collateral data
160
+
161
+ **Raises:**
162
+ - `ValueError`: If quote is invalid or FMSPC cannot be extracted
163
+ - `RuntimeError`: If network request fails
164
+ - `ImportError`: If requests library is not available
165
+
166
+ #### `get_collateral_and_verify(raw_quote: bytes, pccs_url: Optional[str] = None) -> VerifiedReport`
167
+
168
+ Get collateral and verify quote in one step.
169
+
170
+ **Parameters:**
171
+ - `raw_quote`: Raw quote data as bytes
172
+ - `pccs_url`: Optional PCCS URL (uses Intel PCS if None)
173
+
174
+ **Returns:**
175
+ - `VerifiedReport`: Verification results
176
+
177
+ **Raises:**
178
+ - `ValueError`: If quote is invalid or verification fails
179
+ - `RuntimeError`: If network request fails
180
+ - `ImportError`: If requests library is not available
181
+
182
+ **Example:**
183
+ ```python
184
+ import dcap_qvl
185
+
186
+ quote_data = open("quote.bin", "rb").read()
187
+ result = dcap_qvl.get_collateral_and_verify(quote_data)
188
+ print(f"Status: {result.status}")
189
+ print(f"Advisory IDs: {result.advisory_ids}")
190
+ ```
191
+
192
+ ### Classes
193
+
194
+ #### `QuoteCollateralV3`
195
+
196
+ Represents quote collateral data required for verification.
197
+
198
+ **Constructor:**
199
+ ```python
200
+ QuoteCollateralV3(
201
+ pck_crl_issuer_chain: str,
202
+ root_ca_crl: bytes,
203
+ pck_crl: bytes,
204
+ tcb_info_issuer_chain: str,
205
+ tcb_info: str,
206
+ tcb_info_signature: bytes,
207
+ qe_identity_issuer_chain: str,
208
+ qe_identity: str,
209
+ qe_identity_signature: bytes,
210
+ )
211
+ ```
212
+
213
+ **Methods:**
214
+ - `to_json() -> str`: Serialize to JSON string
215
+ - `from_json(json_str: str) -> QuoteCollateralV3`: Create from JSON string (static method)
216
+
217
+ **Properties:**
218
+ - `pck_crl_issuer_chain: str`
219
+ - `root_ca_crl: bytes`
220
+ - `pck_crl: bytes`
221
+ - `tcb_info_issuer_chain: str`
222
+ - `tcb_info: str`
223
+ - `tcb_info_signature: bytes`
224
+ - `qe_identity_issuer_chain: str`
225
+ - `qe_identity: str`
226
+ - `qe_identity_signature: bytes`
227
+
228
+ #### `VerifiedReport`
229
+
230
+ Contains the results of quote verification.
231
+
232
+ **Properties:**
233
+ - `status: str`: Verification status
234
+ - `advisory_ids: List[str]`: List of advisory IDs
235
+
236
+ **Methods:**
237
+ - `to_json() -> str`: Serialize to JSON string
238
+
239
+ ### Functions
240
+
241
+ #### `verify(raw_quote: bytes, collateral: QuoteCollateralV3, now_secs: int) -> VerifiedReport`
242
+
243
+ Verify a quote with the provided collateral data.
244
+
245
+ **Parameters:**
246
+ - `raw_quote`: Raw quote data as bytes
247
+ - `collateral`: Quote collateral data
248
+ - `now_secs`: Current timestamp in seconds since Unix epoch
249
+
250
+ **Returns:**
251
+ - `VerifiedReport`: Verification results
252
+
253
+ **Raises:**
254
+ - `ValueError`: If verification fails
255
+
256
+ ## Development
257
+
258
+ ### Building from Source
259
+
260
+ If you want to build from source or contribute to development:
261
+
262
+ ```bash
263
+ # Clone the repository
264
+ git clone https://github.com/Phala-Network/dcap-qvl.git
265
+ cd dcap-qvl/python-bindings
266
+
267
+ # Install development dependencies (including maturin)
268
+ uv sync
269
+
270
+ # Build and install the Python extension in development mode
271
+ uv run maturin develop --features python
272
+
273
+ # Run tests
274
+ uv run python -m pytest tests/test_python_bindings.py
275
+ ```
276
+
277
+ **Note:** maturin is only required for building from source. Regular users installing from PyPI don't need maturin.
278
+
279
+ ### Running Examples
280
+
281
+ After installing the package, you can run the examples:
282
+
283
+ ```bash
284
+ # Download the examples from the repository
285
+ git clone https://github.com/Phala-Network/dcap-qvl.git
286
+ cd dcap-qvl/python-bindings
287
+
288
+ # Basic functionality test
289
+ python examples/basic_test.py
290
+
291
+ # Full example (requires sample data files)
292
+ python examples/python_example.py
293
+ ```
294
+
295
+ Or if you're using uv for development:
296
+
297
+ ```bash
298
+ # Basic functionality test
299
+ uv run python examples/basic_test.py
300
+
301
+ # Full example (requires sample data files)
302
+ uv run python examples/python_example.py
303
+ ```
304
+
305
+ ### Testing Across Python Versions
306
+
307
+ The project includes comprehensive testing across all supported Python versions:
308
+
309
+ ```bash
310
+ # Quick test across all Python versions
311
+ make test_python_versions
312
+
313
+ # Test current Python version only
314
+ make test_python
315
+ ```
316
+
317
+ See [PYTHON_TESTING.md](PYTHON_TESTING.md) for detailed information about Python version compatibility testing.
318
+
319
+ ## Requirements
320
+
321
+ ### For regular usage (installing from PyPI):
322
+ - Python 3.8+
323
+
324
+ ### For development (building from source):
325
+ - Python 3.8+
326
+ - Rust toolchain (rustc, cargo)
327
+ - maturin (automatically installed with `uv sync`)
328
+
329
+ ## License
330
+
331
+ MIT License - see [LICENSE](LICENSE) for details.
332
+
333
+ ## Contributing
334
+
335
+ Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1,6 @@
1
+ dcap_qvl-0.3.0.dist-info/METADATA,sha256=kvyMT6Itp-hO2M6MYH4PJf7I6bPgg76zBgt7vVn_tq8,8444
2
+ dcap_qvl-0.3.0.dist-info/WHEEL,sha256=UYFO5QaLVupuR-8PjNErl5r8k6RNsE-tnSPUE-nT_d4,102
3
+ dcap_qvl/__init__.py,sha256=97qhIqmR6uq7C4AszgmAPP7LcLekvKZOFYmaT3yAaJM,6361
4
+ dcap_qvl/__init__.pyi,sha256=_4GK8CWuFUeewS8ZKk9kiy96hXn4ypDc2rnFpY0g6bQ,9362
5
+ dcap_qvl/dcap_qvl.abi3.so,sha256=TQ1WzAChRR_p4FlRk2C58_ga45hv46MAbivY2vhPXOA,5236016
6
+ dcap_qvl-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.9.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp37-abi3-macosx_11_0_arm64